]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pcre: use pcre2 to parse detect pcre itself
authorPhilippe Antoine <contact@catenacyber.fr>
Wed, 7 Apr 2021 08:58:17 +0000 (10:58 +0200)
committerPhilippe Antoine <contact@catenacyber.fr>
Tue, 28 Sep 2021 15:46:19 +0000 (17:46 +0200)
src/detect-parse.c
src/detect-parse.h
src/detect-pcre.c
src/detect-pcre.h

index 909c2f14775eefc89c154ce850ff738167f91a9d..cdbcc788159214a20de87accac6e331a997da156 100644 (file)
@@ -2458,6 +2458,21 @@ void DetectParseFreeRegex(DetectParseRegex *r)
     }
 }
 
+void DetectParseFreePCRE2(DetectParseRegex2 *r)
+{
+    if (r->regex) {
+        pcre2_code_free(r->regex);
+    }
+    if (r->context) {
+        pcre2_match_context_free(r->context);
+    }
+    if (r->match) {
+        pcre2_match_data_free(r->match);
+    }
+}
+
+static DetectParseRegex2 *g_detect_pcre2_list = NULL;
+
 void DetectParseFreeRegexes(void)
 {
     DetectParseRegex *r = g_detect_parse_regex_list;
@@ -2470,6 +2485,15 @@ void DetectParseFreeRegexes(void)
         r = next;
     }
     g_detect_parse_regex_list = NULL;
+
+    DetectParseRegex2 *r2 = g_detect_pcre2_list;
+    while (r2) {
+        DetectParseRegex2 *next = r2->next;
+        DetectParseFreePCRE2(r2);
+        SCFree(r2);
+        r2 = next;
+    }
+    g_detect_pcre2_list = NULL;
 }
 
 /** \brief add regex and/or study to at exit free list
@@ -2510,6 +2534,42 @@ bool DetectSetupParseRegexesOpts(const char *parse_str, DetectParseRegex *detect
     return true;
 }
 
+/** \brief add pcre2 to at exit free list
+ */
+static void DetectPCRE2AddToFreeList(DetectParseRegex2 *detect_parse)
+{
+    // TODO g_detect_parse_regex_list
+    detect_parse->next = g_detect_pcre2_list;
+    g_detect_pcre2_list = detect_parse;
+}
+
+DetectParseRegex2 *DetectSetupPCRE2(const char *parse_str, int opts)
+{
+    int en;
+    PCRE2_SIZE eo;
+    DetectParseRegex2 *detect_parse = SCCalloc(1, sizeof(DetectParseRegex2));
+    if (detect_parse == NULL) {
+        return NULL;
+    }
+
+    detect_parse->regex =
+            pcre2_compile((PCRE2_SPTR8)parse_str, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
+    if (detect_parse->regex == NULL) {
+        PCRE2_UCHAR errbuffer[256];
+        pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
+        SCLogError(SC_ERR_PCRE_COMPILE,
+                "pcre2 compile of \"%s\" failed at "
+                "offset %d: %s",
+                parse_str, (int)eo, errbuffer);
+        SCFree(detect_parse);
+        return NULL;
+    }
+    detect_parse->match = pcre2_match_data_create_from_pattern(detect_parse->regex, NULL);
+
+    DetectPCRE2AddToFreeList(detect_parse);
+    return detect_parse;
+}
+
 void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
 {
     if (!DetectSetupParseRegexesOpts(parse_str, detect_parse, 0)) {
index 5f63915de6f05aaedf1a787854981ab9581bce49..b0dd476c9e8f24f25b1f0ce8e5075021aeb6142a 100644 (file)
@@ -45,6 +45,15 @@ typedef struct DetectParseRegex_ {
     struct DetectParseRegex_ *next;
 } DetectParseRegex;
 
+#include <pcre2.h>
+
+typedef struct DetectParseRegex2 {
+    pcre2_code *regex;
+    pcre2_match_context *context;
+    pcre2_match_data *match;
+    struct DetectParseRegex2 *next;
+} DetectParseRegex2;
+
 /* prototypes */
 Signature *SigAlloc(void);
 void SigFree(DetectEngineCtx *de_ctx, Signature *s);
@@ -85,6 +94,8 @@ int WARN_UNUSED DetectSignatureSetAppProto(Signature *s, AppProto alproto);
 
 /* parse regex setup and free util funcs */
 
+void DetectParseFreePCRE2(DetectParseRegex2 *r);
+DetectParseRegex2 *DetectSetupPCRE2(const char *parse_str, int opts);
 bool DetectSetupParseRegexesOpts(const char *parse_str, DetectParseRegex *parse_regex, int opts);
 void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *parse_regex);
 void DetectParseRegexAddToFreeList(DetectParseRegex *parse_regex);
index be462dae672128a2a04a58d3bf6d3b313affcdf0..1b5aca139dba9c44d47661d952f1ee17a6af6770 100644 (file)
@@ -71,8 +71,8 @@
 static int pcre_match_limit = 0;
 static int pcre_match_limit_recursion = 0;
 
-static DetectParseRegex parse_regex;
-static DetectParseRegex parse_capture_regex;
+static DetectParseRegex2 *parse_regex;
+static DetectParseRegex2 *parse_capture_regex;
 
 #ifdef PCRE2_HAVE_JIT
 static int pcre2_use_jit = 1;
@@ -80,14 +80,13 @@ static int pcre2_use_jit = 1;
 
 // TODOpcre2 pcre2_jit_stack_create ?
 
-/* \brief Helper function for using pcre_exec with/without JIT
+/* \brief Helper function for using pcre2_match with/without JIT
  */
 static inline int DetectPcreExec(DetectEngineThreadCtx *det_ctx, DetectPcreData *pd,
         const char *str, const size_t strlen, int start_offset, int options)
 {
-    /* Fallback if registration during setup failed */
     return pcre2_match(pd->parse_regex.regex, (PCRE2_SPTR8)str, strlen, start_offset, options,
-            pd->parse_regex.match, NULL);
+            pd->parse_regex.match, pd->parse_regex.context);
 }
 
 static int DetectPcreSetup (DetectEngineCtx *, Signature *, const char *);
@@ -139,12 +138,16 @@ void DetectPcreRegister (void)
         }
     }
 
-    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
+    parse_regex = DetectSetupPCRE2(PARSE_REGEX, 0);
+    if (parse_regex == NULL) {
+        FatalError(SC_ERR_PCRE_COMPILE, "pcre2 compile failed for parse_regex");
+    }
 
-    /* setup the capture regex, as it needs PCRE_UNGREEDY we do it manually */
+    /* setup the capture regex, as it needs PCRE2_UNGREEDY we do it manually */
     /* pkt_http_ua should be pkt, http_ua, for this reason the UNGREEDY */
-    if (!DetectSetupParseRegexesOpts(PARSE_CAPTURE_REGEX, &parse_capture_regex, PCRE_UNGREEDY)) {
-        FatalError(SC_ERR_PCRE_COMPILE, "pcre compile and study failed");
+    parse_capture_regex = DetectSetupPCRE2(PARSE_CAPTURE_REGEX, PCRE2_UNGREEDY);
+    if (parse_capture_regex == NULL) {
+        FatalError(SC_ERR_PCRE_COMPILE, "pcre2 compile failed for parse_capture_regex");
     }
 
 #ifdef PCRE2_HAVE_JIT
@@ -280,6 +283,9 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
                         (void)DetectVarStoreMatch(det_ctx, pe->capids[x],
                                 (uint8_t *)str_ptr, capture_len,
                                 DETECT_VAR_TYPE_FLOW_POSTMATCH);
+                    } else {
+                        BUG_ON("Impossible captype");
+                        SCFree(str_ptr);
                     }
                 }
             }
@@ -351,7 +357,6 @@ static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx,
     DetectPcreData *pd = NULL;
     char *op = NULL;
     int ret = 0, res = 0;
-    int ov[MAX_SUBSTRINGS];
     int check_host_header = 0;
     char op_str[64] = "";
 
@@ -396,23 +401,23 @@ static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx,
     }
 
     char re[slen];
-    ret = pcre_exec(parse_regex.regex, parse_regex.study, regexstr,
-            slen, 0, 0, ov, MAX_SUBSTRINGS);
+    ret = pcre2_match(
+            parse_regex->regex, (PCRE2_SPTR8)regexstr, slen, 0, 0, parse_regex->match, NULL);
     if (ret <= 0) {
         SCLogError(SC_ERR_PCRE_MATCH, "pcre parse error: %s", regexstr);
         goto error;
     }
 
-    res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS,
-            1, re, slen);
+    res = pcre2_substring_copy_bynumber(parse_regex->match, 1, (PCRE2_UCHAR8 *)re, &slen);
     if (res < 0) {
         SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
         return NULL;
     }
 
     if (ret > 2) {
-        res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS,
-                2, op_str, sizeof(op_str));
+        size_t copylen = sizeof(op_str);
+        res = pcre2_substring_copy_bynumber(
+                parse_regex->match, 2, (PCRE2_UCHAR8 *)op_str, &copylen);
         if (res < 0) {
             SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
             return NULL;
@@ -675,7 +680,7 @@ static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx,
         }
     } else {
         pcre2_set_match_limit(pd->parse_regex.context, SC_MATCH_LIMIT_DEFAULT);
-        pcre2_set_recursion_limit(pd->parse_regex.context, PCRE_EXTRA_MATCH_LIMIT_RECURSION);
+        pcre2_set_recursion_limit(pd->parse_regex.context, SC_MATCH_LIMIT_RECURSION_DEFAULT);
     }
     return pd;
 
@@ -691,14 +696,13 @@ static int DetectPcreParseCapture(const char *regexstr, DetectEngineCtx *de_ctx,
     char *capture_names)
 {
     int ret = 0, res = 0;
-    int ov[MAX_SUBSTRINGS];
-    memset(&ov, 0, sizeof(ov));
     char type_str[16] = "";
     const char *orig_right_edge = regexstr + strlen(regexstr);
     char *name_array[DETECT_PCRE_CAPTURE_MAX] = { NULL };
     int name_idx = 0;
     int capture_cnt = 0;
     int key = 0;
+    size_t copylen;
 
     SCLogDebug("regexstr %s, pd %p", regexstr, pd);
 
@@ -768,19 +772,22 @@ static int DetectPcreParseCapture(const char *regexstr, DetectEngineCtx *de_ctx,
     while (1) {
         SCLogDebug("\'%s\'", regexstr);
 
-        ret = pcre_exec(parse_capture_regex.regex, parse_capture_regex.study, regexstr,
-                strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS);
+        ret = pcre2_match(parse_capture_regex->regex, (PCRE2_SPTR8)regexstr, strlen(regexstr), 0, 0,
+                parse_capture_regex->match, NULL);
         if (ret < 3) {
             return 0;
         }
-
-        res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, type_str, sizeof(type_str));
-        if (res < 0) {
+        copylen = sizeof(type_str);
+        res = pcre2_substring_copy_bynumber(
+                parse_capture_regex->match, 1, (PCRE2_UCHAR8 *)type_str, &copylen);
+        if (res != 0) {
             SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
             goto error;
         }
-        res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 2, capture_str, cap_buffer_len);
-        if (res < 0) {
+        cap_buffer_len = strlen(regexstr) + 1;
+        res = pcre2_substring_copy_bynumber(
+                parse_capture_regex->match, 2, (PCRE2_UCHAR8 *)capture_str, &cap_buffer_len);
+        if (res != 0) {
             SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
             goto error;
         }
@@ -809,6 +816,7 @@ static int DetectPcreParseCapture(const char *regexstr, DetectEngineCtx *de_ctx,
         }
 
         //SCLogNotice("pd->capname %s", pd->capname);
+        PCRE2_SIZE *ov = pcre2_get_ovector_pointer(parse_capture_regex->match);
         regexstr += ov[1];
 
         if (regexstr >= orig_right_edge)
@@ -923,9 +931,7 @@ static void DetectPcreFree(DetectEngineCtx *de_ctx, void *ptr)
         return;
 
     DetectPcreData *pd = (DetectPcreData *)ptr;
-    pcre2_code_free(pd->parse_regex.regex);
-    pcre2_match_context_free(pd->parse_regex.context);
-    pcre2_match_data_free(pd->parse_regex.match);
+    DetectParseFreePCRE2(&pd->parse_regex);
     SCFree(pd);
 
     return;
index d09a4c0e4e138dad89e78d2eede3792343dca499..f18631790a0074f764ba62c36345b4633767ef92 100644 (file)
 
 #define DETECT_PCRE_CAPTURE_MAX         8
 
-#include <pcre2.h>
-
-typedef struct DetectParseRegex2 {
-    pcre2_code *regex;
-    pcre2_match_context *context;
-    pcre2_match_data *match;
-    // struct DetectParseRegex2 *next;
-} DetectParseRegex2;
-
 typedef struct DetectPcreData_ {
     /* pcre options */
     DetectParseRegex2 parse_regex;