From: Philippe Antoine Date: Wed, 7 Apr 2021 08:58:17 +0000 (+0200) Subject: pcre: use pcre2 to parse detect pcre itself X-Git-Tag: suricata-7.0.0-beta1~1347 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2dea9a1e3758d458c801db4ccaf1f9069adc7625;p=thirdparty%2Fsuricata.git pcre: use pcre2 to parse detect pcre itself --- diff --git a/src/detect-parse.c b/src/detect-parse.c index 909c2f1477..cdbcc78815 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -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)) { diff --git a/src/detect-parse.h b/src/detect-parse.h index 5f63915de6..b0dd476c9e 100644 --- a/src/detect-parse.h +++ b/src/detect-parse.h @@ -45,6 +45,15 @@ typedef struct DetectParseRegex_ { struct DetectParseRegex_ *next; } DetectParseRegex; +#include + +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); diff --git a/src/detect-pcre.c b/src/detect-pcre.c index be462dae67..1b5aca139d 100644 --- a/src/detect-pcre.c +++ b/src/detect-pcre.c @@ -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, ©len); 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, ©len); + 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; diff --git a/src/detect-pcre.h b/src/detect-pcre.h index d09a4c0e4e..f18631790a 100644 --- a/src/detect-pcre.h +++ b/src/detect-pcre.h @@ -36,15 +36,6 @@ #define DETECT_PCRE_CAPTURE_MAX 8 -#include - -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;