1 From 514af7b25f1f49d87963baf4fd057d9c85f518a7 Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Sat, 4 Nov 2023 01:30:37 +0100
4 Subject: [PATCH] Convert project to PCRE2
6 Convert project to PCRE2. Convert every example to PCRE2.
8 Due to API changes examples needs to be updated accordingly with the new
11 The API name were voluntary changes to make sure the user of plugins is
12 aware of the change and manually refresh the plugin with new code.
14 Most of the time it's just PcreMatch to Pcre2Match and PCREInfo to
15 PCRE2Info and the relative options (that are 1:1 compared to PCRE
18 For complex case where ovector extraction is needed, refer to example
19 36733 where new way with match data is used. Follow comments there for
22 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
25 configure.in | 67 ++++----
26 src/detection-plugins/sp_pcre.c | 149 +++++++++---------
27 src/detection-plugins/sp_pcre.h | 9 +-
28 src/dynamic-plugins/sf_convert_dynamic.c | 59 ++++---
29 src/dynamic-plugins/sf_dynamic_engine.h | 32 ++--
30 src/dynamic-plugins/sf_dynamic_plugins.c | 109 +++++++------
31 src/dynamic-plugins/sf_engine/examples/3036.c | 8 +-
32 src/dynamic-plugins/sf_engine/examples/3052.c | 8 +-
33 src/dynamic-plugins/sf_engine/examples/3099.c | 8 +-
34 .../sf_engine/examples/36733.c | 40 +++--
35 src/dynamic-plugins/sf_engine/examples/3682.c | 11 +-
36 .../sf_engine/examples/bug31842.c | 9 +-
37 .../sf_engine/examples/bug35218.c | 15 +-
38 .../sf_engine/examples/sid1902.c | 9 +-
39 .../sf_engine/examples/sid2389.c | 9 +-
40 .../sf_engine/examples/sid9999.c | 2 +-
41 .../sf_engine/examples/web-client_test.c | 18 +--
42 .../sf_engine/sf_snort_detection_engine.c | 20 +--
43 .../sf_engine/sf_snort_detection_engine.h | 2 +-
44 .../sf_engine/sf_snort_plugin_api.c | 10 +-
45 .../sf_engine/sf_snort_plugin_api.h | 39 +++--
46 .../sf_engine/sf_snort_plugin_pcre.c | 132 ++++++++++------
47 .../appid/luaDetectorApi.c | 63 +++++---
48 src/dynamic-preprocessors/imap/snort_imap.h | 6 +-
49 src/dynamic-preprocessors/pop/snort_pop.h | 3 +-
50 src/dynamic-preprocessors/smtp/snort_smtp.h | 3 +-
54 30 files changed, 497 insertions(+), 364 deletions(-)
55 mode change 100755 => 100644 src/dynamic-plugins/sf_engine/sf_snort_plugin_api.h
56 mode change 100755 => 100644 src/dynamic-plugins/sf_engine/sf_snort_plugin_pcre.c
61 /* Define to 1 if you have the `pcap' library (-lpcap). */
64 -/* Define to 1 if you have the `pcre' library (-lpcre). */
66 +/* Define to 1 if you have the `pcre2' library (-lpcre2-8). */
69 /* Define to 1 if you have the `pfring' library (-lpfring). */
72 /* Can output the library version. */
73 #undef HAVE_PCAP_LIB_VERSION
75 -/* Define to 1 if you have the <pcre.h> header file. */
77 +/* Define to 1 if you have the <pcre2.h> header file. */
80 /* Define to 1 if you have the <pfring.h> header file. */
84 @@ -455,65 +455,70 @@ AC_DEFUN([FAIL_MESSAGE],[
88 -AC_ARG_WITH(libpcre_includes,
89 - [ --with-libpcre-includes=DIR libpcre include directory],
90 - [with_libpcre_includes="$withval"],[with_libpcre_includes="no"])
92 -AC_ARG_WITH(libpcre_libraries,
93 - [ --with-libpcre-libraries=DIR libpcre library directory],
94 - [with_libpcre_libraries="$withval"],[with_libpcre_libraries="no"])
96 -if test "x$with_libpcre_includes" != "xno"; then
97 - CPPFLAGS="${CPPFLAGS} -I${with_libpcre_includes}"
98 - ICONFIGFLAGS="${ICONFIGFLAGS} -I${with_libpcre_includes}"
99 +AC_ARG_WITH(libpcre2_includes,
100 + [ --with-libpcre2-includes=DIR libpcre2 include directory],
101 + [with_libpcre2_includes="$withval"],[with_libpcre2_includes="no"])
103 +AC_ARG_WITH(libpcre2_libraries,
104 + [ --with-libpcre2-libraries=DIR libpcre2 library directory],
105 + [with_libpcre2_libraries="$withval"],[with_libpcre2_libraries="no"])
107 +if test "x$with_libpcre2_includes" != "xno"; then
108 + CPPFLAGS="${CPPFLAGS} -I${with_libpcre2_includes}"
109 + ICONFIGFLAGS="${ICONFIGFLAGS} -I${with_libpcre2_includes}"
111 - CPPFLAGS="${CPPFLAGS} `pcre-config --cflags`"
112 + CPPFLAGS="${CPPFLAGS} `pcre2-config --cflags`"
115 -if test "x$with_libpcre_libraries" != "xno"; then
116 - LDFLAGS="${LDFLAGS} -L${with_libpcre_libraries}"
117 +if test "x$with_libpcre2_libraries" != "xno"; then
118 + LDFLAGS="${LDFLAGS} -L${with_libpcre2_libraries}"
120 - LDFLAGS="${LDFLAGS} `pcre-config --libs`"
121 + LDFLAGS="${LDFLAGS} `pcre2-config --libs8`"
124 -# PCRE configuration (required)
125 +# PCRE2 configuration (required)
126 # Verify that we have the headers
128 -AC_CHECK_HEADERS(pcre.h,, PCRE_H="no")
129 -if test "x$PCRE_H" = "xno"; then
131 +AC_CHECK_HEADERS(pcre2.h,, PCRE2_H="no",[#define PCRE2_CODE_UNIT_WIDTH 8])
132 +if test "x$PCRE2_H" = "xno"; then
134 - echo " ERROR! Libpcre header not found."
135 + echo " ERROR! Libpcre2 header not found."
136 echo " Get it from http://www.pcre.org"
140 # Verify that we have the library
143 -AC_CHECK_LIB(pcre, pcre_compile, ,PCRE_L="no")
145 +pcre2_version_six=""
146 +AC_CHECK_LIB(pcre2-8, pcre2_compile_8, ,PCRE2_L="no")
147 if test "x$PCRE_L" = "xno"; then
149 - echo " ERROR! Libpcre library not found."
150 + echo " ERROR! Libpcre2 library not found."
151 echo " Get it from http://www.pcre.org"
155 - AC_MSG_CHECKING(for libpcre version 6.0 or greater)
156 - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pcre.h>]], [[
157 - #if (PCRE_MAJOR < 6)
158 + AC_MSG_CHECKING(for libpcre2 version 10.0 or greater)
159 + AC_LINK_IFELSE([AC_LANG_PROGRAM([[
160 + #define PCRE2_CODE_UNIT_WIDTH 8
163 + #if (PCRE2_MAJOR < 10)
164 #error "Version failure"
166 - int a, b = 0, c = 0, d = 0;
168 - a = pcre_copy_named_substring(tmp, "", &b, c, "", "", d);
170 + PCRE2_UCHAR b = { 0 };
172 + pcre2_match_data *match_data = NULL;
173 + a = pcre2_substring_copy_byname(match_data, (PCRE2_SPTR )"", &b, &c);
175 - ]])],[pcre_version_six="yes"],[pcre_version_six="no"])
176 + ]])],[pcre2_version_ten="yes"],[pcre2_version_ten="no"])
179 -if test "x$pcre_version_six" != "xyes"; then
180 +if test "x$pcre2_version_ten" != "xyes"; then
183 - echo " ERROR! Libpcre library version >= 6.0 not found."
184 + echo " ERROR! Libpcre2 library version >= 10.0 not found."
185 echo " Get it from http://www.pcre.org"
188 --- a/src/detection-plugins/sp_pcre.c
189 +++ b/src/detection-plugins/sp_pcre.c
195 +#define PCRE2_CODE_UNIT_WIDTH 8
199 #include "profiler.h"
200 @@ -60,7 +61,7 @@ extern PreprocStats ruleOTNEvalPerfStats
201 #include "detection_util.h"
204 - * we need to specify the vector length for our pcre_exec call. we only care
205 + * we need to specify the vector length for our pcre2_match call. we only care
206 * about the first vector, which if the match is successful will include the
207 * offset to the end of the full pattern match. If we decide to store other
208 * matches, make *SURE* that this is a multiple of 3 as pcre requires it.
209 @@ -77,8 +78,8 @@ void PcreFree(void *d)
210 PcreData *data = (PcreData *)d;
212 free(data->expression);
215 + pcre2_match_context_free(data->match_context);
216 + pcre2_code_free(data->re);
220 @@ -161,7 +162,6 @@ void PcreDuplicatePcreData(void *src, Pc
221 pcre_dup->expression = pcre_src->expression;
222 pcre_dup->options = pcre_src->options;
223 pcre_dup->search_offset = 0;
224 - pcre_dup->pe = pcre_src->pe;
225 pcre_dup->re = pcre_src->re;
228 @@ -197,7 +197,7 @@ static void Ovector_Init(struct _SnortCo
229 * configuraton, we won't pcre capture count again, so save the max. */
230 static int s_ovector_max = 0;
232 - /* The pcre_fullinfo() function can be used to find out how many
233 + /* The pcre2_pattern_info() function can be used to find out how many
234 * capturing subpatterns there are in a compiled pattern. The
235 * smallest size for ovector that will allow for n captured
236 * substrings, in addition to the offsets of the substring matched
237 @@ -207,8 +207,6 @@ static void Ovector_Init(struct _SnortCo
239 if (sc->pcre_ovector_size > s_ovector_max)
240 s_ovector_max = sc->pcre_ovector_size;
242 - sc->pcre_ovector = (int *) SnortAlloc(s_ovector_max*sizeof(int));
246 @@ -218,12 +216,12 @@ static void Ovector_Reload(struct _Snort
250 -void PcreCapture(struct _SnortConfig *sc, const void *code, const void *extra)
251 +void Pcre2Capture(struct _SnortConfig *sc, const void *code)
253 int tmp_ovector_size = 0;
255 - pcre_fullinfo((const pcre *)code, (const pcre_extra *)extra,
256 - PCRE_INFO_CAPTURECOUNT, &tmp_ovector_size);
257 + pcre2_pattern_info((const pcre2_code *)code,
258 + PCRE2_INFO_CAPTURECOUNT, &tmp_ovector_size);
260 if (tmp_ovector_size > sc->pcre_ovector_size)
261 sc->pcre_ovector_size = tmp_ovector_size;
262 @@ -268,10 +266,10 @@ void SnortPcreInit(struct _SnortConfig *
264 if (pcre_data->expression)
265 free(pcre_data->expression);
267 - free(pcre_data->pe);
268 + if (pcre_data->match_context)
269 + pcre2_match_context_free(pcre_data->match_context);
271 - free(pcre_data->re);
272 + pcre2_code_free(pcre_data->re);
275 pcre_data = pcre_dup;
276 @@ -305,11 +303,12 @@ static inline void ValidatePcreHttpConte
278 void SnortPcreParse(struct _SnortConfig *sc, char *data, PcreData *pcre_data, OptTreeNode *otn)
281 + PCRE2_UCHAR error[128];
287 + PCRE2_SIZE erroffset;
288 int compile_flags = 0;
291 @@ -381,17 +380,17 @@ void SnortPcreParse(struct _SnortConfig
292 /* process any /regex/ismxR options */
293 while(*opts != '\0') {
295 - case 'i': compile_flags |= PCRE_CASELESS; break;
296 - case 's': compile_flags |= PCRE_DOTALL; break;
297 - case 'm': compile_flags |= PCRE_MULTILINE; break;
298 - case 'x': compile_flags |= PCRE_EXTENDED; break;
299 + case 'i': compile_flags |= PCRE2_CASELESS; break;
300 + case 's': compile_flags |= PCRE2_DOTALL; break;
301 + case 'm': compile_flags |= PCRE2_MULTILINE; break;
302 + case 'x': compile_flags |= PCRE2_EXTENDED; break;
305 * these are pcre specific... don't work with perl
307 - case 'A': compile_flags |= PCRE_ANCHORED; break;
308 - case 'E': compile_flags |= PCRE_DOLLAR_ENDONLY; break;
309 - case 'G': compile_flags |= PCRE_UNGREEDY; break;
310 + case 'A': compile_flags |= PCRE2_ANCHORED; break;
311 + case 'E': compile_flags |= PCRE2_DOLLAR_ENDONLY; break;
312 + case 'G': compile_flags |= PCRE2_UNGREEDY; break;
315 * these are snort specific don't work with pcre or perl
316 @@ -424,45 +423,37 @@ void SnortPcreParse(struct _SnortConfig
318 /* now compile the re */
319 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre: compiling %s\n", re););
320 - pcre_data->re = pcre_compile(re, compile_flags, &error, &erroffset, NULL);
321 + pcre_data->re = pcre2_compile((PCRE2_SPTR)re, PCRE2_ZERO_TERMINATED, compile_flags, &errorcode, &erroffset, NULL);
323 if(pcre_data->re == NULL)
325 + pcre2_get_error_message(errorcode, error, 128);
326 FatalError("%s(%d) : pcre compile of \"%s\" failed at offset "
327 - "%d : %s\n", file_name, file_line, re, erroffset, error);
328 + "%zu : %s\n", file_name, file_line, re, erroffset, error);
331 + /* now create match context */
332 + pcre_data->match_context = pcre2_match_context_create(NULL);
333 + if(pcre_data->match_context == NULL)
335 + FatalError("%s(%d) : failed to allocate memory for match context\n",
336 + file_name, file_line);
339 /* now study it... */
340 - pcre_data->pe = pcre_study(pcre_data->re, 0, &error);
341 + errorcode = pcre2_jit_compile(pcre_data->re, PCRE2_JIT_COMPLETE);
346 if ((ScPcreMatchLimitNewConf(sc) != -1) && !(pcre_data->options & SNORT_OVERRIDE_MATCH_LIMIT))
348 - if (pcre_data->pe->flags & PCRE_EXTRA_MATCH_LIMIT)
350 - pcre_data->pe->match_limit = ScPcreMatchLimitNewConf(sc);
354 - pcre_data->pe->flags |= PCRE_EXTRA_MATCH_LIMIT;
355 - pcre_data->pe->match_limit = ScPcreMatchLimitNewConf(sc);
357 + pcre2_set_match_limit(pcre_data->match_context, ScPcreMatchLimitNewConf(sc));
360 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
361 if ((ScPcreMatchLimitRecursionNewConf(sc) != -1) && !(pcre_data->options & SNORT_OVERRIDE_MATCH_LIMIT))
363 - if (pcre_data->pe->flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION)
365 - pcre_data->pe->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
369 - pcre_data->pe->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
370 - pcre_data->pe->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
372 + pcre2_set_depth_limit(pcre_data->match_context, ScPcreMatchLimitRecursionNewConf(sc));
376 @@ -471,30 +462,28 @@ void SnortPcreParse(struct _SnortConfig
377 if (!(pcre_data->options & SNORT_OVERRIDE_MATCH_LIMIT) &&
378 ((ScPcreMatchLimitNewConf(sc) != -1) || (ScPcreMatchLimitRecursionNewConf(sc) != -1)))
380 - pcre_data->pe = (pcre_extra *)SnortAlloc(sizeof(pcre_extra));
381 if (ScPcreMatchLimitNewConf(sc) != -1)
383 - pcre_data->pe->flags |= PCRE_EXTRA_MATCH_LIMIT;
384 - pcre_data->pe->match_limit = ScPcreMatchLimitNewConf(sc);
385 + pcre2_set_match_limit(pcre_data->match_context, ScPcreMatchLimitNewConf(sc));
388 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
389 if (ScPcreMatchLimitRecursionNewConf(sc) != -1)
391 - pcre_data->pe->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
392 - pcre_data->pe->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
393 + pcre2_set_depth_limit(pcre_data->match_context, ScPcreMatchLimitRecursionNewConf(sc));
402 + pcre2_get_error_message(errorcode, error, 128);
403 FatalError("%s(%d) : pcre study failed : %s\n", file_name,
407 - PcreCapture(sc, pcre_data->re, pcre_data->pe);
408 + Pcre2Capture(sc, pcre_data->re);
410 PcreCheckAnchored(pcre_data);
412 @@ -515,13 +504,13 @@ void PcreCheckAnchored(PcreData *pcre_da
414 unsigned long int options = 0;
416 - if ((pcre_data == NULL) || (pcre_data->re == NULL) || (pcre_data->pe == NULL))
417 + if ((pcre_data == NULL) || (pcre_data->re == NULL) || (pcre_data->match_context == NULL))
420 - rc = pcre_fullinfo(pcre_data->re, pcre_data->pe, PCRE_INFO_OPTIONS, (void *)&options);
421 + rc = pcre2_pattern_info(pcre_data->re, PCRE2_INFO_ARGOPTIONS, (void *)&options);
424 - /* pcre_fullinfo fails for the following:
425 + /* pcre2_pattern_info fails for the following:
426 * PCRE_ERROR_NULL - the argument code was NULL
427 * the argument where was NULL
428 * PCRE_ERROR_BADMAGIC - the "magic number" was not found
429 @@ -533,24 +522,24 @@ void PcreCheckAnchored(PcreData *pcre_da
430 /* This is the success code */
433 - case PCRE_ERROR_NULL:
434 - FatalError("%s(%d) pcre_fullinfo: code and/or where were NULL.\n",
435 + case PCRE2_ERROR_NULL:
436 + FatalError("%s(%d) pcre2_pattern_info: code and/or where were NULL.\n",
439 - case PCRE_ERROR_BADMAGIC:
440 - FatalError("%s(%d) pcre_fullinfo: compiled code didn't have "
441 + case PCRE2_ERROR_BADMAGIC:
442 + FatalError("%s(%d) pcre2_pattern_info: compiled code didn't have "
443 "correct magic.\n", __FILE__, __LINE__);
445 - case PCRE_ERROR_BADOPTION:
446 - FatalError("%s(%d) pcre_fullinfo: option type is invalid.\n",
447 + case PCRE2_ERROR_BADOPTION:
448 + FatalError("%s(%d) pcre2_pattern_info: option type is invalid.\n",
452 - FatalError("%s(%d) pcre_fullinfo: Unknown error code.\n",
453 + FatalError("%s(%d) pcre2_pattern_info: Unknown error code.\n",
457 - if ((options & PCRE_ANCHORED) && !(options & PCRE_MULTILINE))
458 + if ((options & PCRE2_ANCHORED) && !(options & PCRE2_MULTILINE))
460 /* This means that this pcre rule option shouldn't be reevaluted
461 * even if any of it's relative children should fail to match.
462 @@ -579,6 +568,8 @@ static int pcre_search(const PcreData *p
466 + pcre2_match_data *match_data;
467 + PCRE2_SIZE *ovector;
471 @@ -596,14 +587,19 @@ static int pcre_search(const PcreData *p
475 - result = pcre_exec(pcre_data->re, /* result of pcre_compile() */
476 - pcre_data->pe, /* result of pcre_study() */
477 - buf, /* the subject string */
478 - len, /* the length of the subject string */
479 - start_offset, /* start at offset 0 in the subject */
480 - 0, /* options(handled at compile time */
481 - snort_conf->pcre_ovector, /* vector for substring information */
482 - snort_conf->pcre_ovector_size);/* number of elements in the vector */
483 + match_data = pcre2_match_data_create(snort_conf->pcre_ovector_size, NULL);
485 + DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre2_match_data_create failed to alloc mem!\n"););
489 + result = pcre2_match(pcre_data->re, /* result of pcre2_compile() */
490 + (PCRE2_SPTR)buf, /* the subject string */
491 + (PCRE2_SIZE)len, /* the length of the subject string */
492 + (PCRE2_SIZE)start_offset, /* start at offset 0 in the subject */
493 + 0, /* options(handled at compile time */
494 + match_data, /* match data for results */
495 + pcre_data->match_context); /* match context for JIT limits */
499 @@ -615,23 +611,25 @@ static int pcre_search(const PcreData *p
500 * second is set to the offset of the first character after the end of a substring. The first pair,
501 * ovector[0] and ovector[1], identify the portion of the subject string matched by the entire pattern.
502 * The next pair is used for the first capturing subpattern, and so on. The value returned by
503 - * pcre_exec() is the number of pairs that have been set. If there are no capturing subpatterns, the
504 + * pcre_match() is the number of pairs that have been set. If there are no capturing subpatterns, the
505 * return value from a successful match is 1, indicating that just the first pair of offsets has been set.
507 * In Snort's case, the ovector size only allows for the first pair and a single int for scratch space.
509 - *found_offset = snort_conf->pcre_ovector[1];
510 + ovector = pcre2_get_ovector_pointer(match_data);
511 + *found_offset = ovector[1];
512 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
513 "Setting Doe_ptr and found_offset: %p %d\n",
514 doe_ptr, found_offset););
516 - else if(result == PCRE_ERROR_NOMATCH)
517 + else if(result == PCRE2_ERROR_NOMATCH)
523 - DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_exec error : %d \n", result););
524 + pcre2_match_data_free(match_data);
525 + DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre2_match error : %d \n", result););
529 @@ -641,6 +639,7 @@ static int pcre_search(const PcreData *p
533 + pcre2_match_data_free(match_data);
537 --- a/src/detection-plugins/sp_pcre.h
538 +++ b/src/detection-plugins/sp_pcre.h
541 void SetupPcre(void);
544 +#define PCRE2_CODE_UNIT_WIDTH 8
546 typedef struct _PcreData
548 - pcre *re; /* compiled regex */
549 - pcre_extra *pe; /* studied regex foo */
550 + pcre2_code *re; /* compiled regex */
551 + pcre2_match_context *match_context; /* regex match context */
552 int options; /* sp_pcre specfic options (relative & inverse) */
554 uint32_t search_offset;
557 -void PcreCapture(struct _SnortConfig *sc, const void *code, const void *extra);
558 +void Pcre2Capture(struct _SnortConfig *sc, const void *code);
559 void PcreFree(void *d);
560 uint32_t PcreHash(void *d);
561 int PcreCompare(void *l, void *r);
562 --- a/src/dynamic-plugins/sf_convert_dynamic.c
563 +++ b/src/dynamic-plugins/sf_convert_dynamic.c
566 extern void ParsePattern(char *, OptTreeNode *, int);
567 extern void ParseProtectedPattern(char *, OptTreeNode *, int);
568 -extern void *pcreCompile(const char *pattern, int options, const char **errptr,
569 - int *erroffset, const unsigned char *tableptr);
570 -extern void *pcreStudy(struct _SnortConfig *sc, const void *code, int options, const char **errptr);
571 +extern void *pcre2MatchContextCreate(const void *gcontext);
572 +extern void *pcre2Compile(const char *pattern, int options, int *errorcode, size_t *erroffset, void *matchcontext);
573 +extern int pcre2JITCompile(struct _SnortConfig *sc, const void *code, const void *matchcontext, int options);
574 +extern void pcre2MatchContextFree(const void *match_context);
575 +extern void pcre2CodeFree(const void *code);
577 extern int SnortPcre(void *option_data, Packet *p);
578 extern int FlowBitsCheck(void *option_data, Packet *p);
579 @@ -517,20 +519,20 @@ static int ConvertProtectedContentOption
580 static int ConvertPcreOption(SnortConfig *sc, Rule *rule, int index, OptTreeNode *otn)
582 PcreData *pcre_data = (PcreData *) SnortAlloc(sizeof(PcreData));
583 - PCREInfo *pcre_info = rule->options[index]->option_u.pcre;
584 + PCRE2Info *pcre2_info = rule->options[index]->option_u.pcre2;
590 + size_t erroroffset;
592 /* Need to recompile the expression so double free doesn't occur
595 /* Compile & Study PCRE */
596 - pcre_data->re = pcreCompile(
598 - pcre_info->compile_flags,
600 + pcre_data->re = pcre2Compile(
602 + pcre2_info->compile_flags,
607 @@ -541,37 +543,46 @@ static int ConvertPcreOption(SnortConfig
611 - pcre_data->pe = pcreStudy(sc,
612 + pcre_data->match_context = pcre2MatchContextCreate(NULL);
613 + if (pcre_data->match_context == NULL) {
614 + pcre2CodeFree(pcre_data->re);
619 + errorcode = pcre2JITCompile(
622 - pcre_info->compile_flags,
624 + pcre_data->match_context,
625 + pcre2_info->compile_flags
631 - free(pcre_data->re);
632 + pcre2MatchContextFree(pcre_data->match_context);
633 + pcre2CodeFree(pcre_data->re);
638 /* Copy to struct used for normal PCRE rules */
639 - pcre_data->expression = SnortStrdup(pcre_info->expr);
640 + pcre_data->expression = SnortStrdup(pcre2_info->expr);
642 /* Option values differ between PCREInfo and PcreData,
643 * so a straight copy of the options variable won't work. */
644 - if (pcre_info->flags & CONTENT_RELATIVE)
645 + if (pcre2_info->flags & CONTENT_RELATIVE)
646 pcre_data->options |= SNORT_PCRE_RELATIVE;
648 - if (pcre_info->flags & NOT_FLAG)
649 + if (pcre2_info->flags & NOT_FLAG)
650 pcre_data->options |= SNORT_PCRE_INVERT;
652 - if (pcre_info->flags & CONTENT_BUF_RAW)
653 + if (pcre2_info->flags & CONTENT_BUF_RAW)
654 pcre_data->options |= SNORT_PCRE_RAWBYTES;
656 - if (pcre_info->flags & CONTENT_BUF_NORMALIZED)
657 + if (pcre2_info->flags & CONTENT_BUF_NORMALIZED)
658 pcre_data->options &= ~SNORT_PCRE_RAWBYTES;
660 - pcre_data->options |= HTTP_CONTENT(pcre_info->flags);
661 + pcre_data->options |= HTTP_CONTENT(pcre2_info->flags);
663 PcreCheckAnchored(pcre_data);
665 @@ -584,10 +595,10 @@ static int ConvertPcreOption(SnortConfig
667 if (pcre_data->expression)
668 free(pcre_data->expression);
670 - free(pcre_data->pe);
671 + if (pcre_data->match_context)
672 + pcre2MatchContextFree(pcre_data->match_context);
674 - free(pcre_data->re);
675 + pcre2CodeFree(pcre_data->re);
678 pcre_data = pcre_dup;
679 --- a/src/dynamic-plugins/sf_dynamic_engine.h
680 +++ b/src/dynamic-plugins/sf_dynamic_engine.h
681 @@ -139,11 +139,18 @@ typedef int (*DynamicDecompressFunc)(voi
683 #define ENGINE_DATA_VERSION 10
685 -typedef void *(*PCRECompileFunc)(const char *, int, const char **, int *, const unsigned char *);
686 -typedef void *(*PCREStudyFunc)(struct _SnortConfig *, const void *, int, const char **);
687 -typedef int (*PCREExecFunc)(const void *, const void *, const char *, int, int, int, int *, int);
688 -typedef void (*PCRECapture)(struct _SnortConfig *, const void *, const void *);
689 -typedef void(*PCREOvectorInfo)(int **, int *);
690 +typedef void *(*PCRE2CompileFunc)(const char *, int, int *, size_t *, void *);
691 +typedef void *(*PCRE2MatchContextCreate)(const void *);
692 +typedef int (*PCRE2JITCompileFunc)(struct _SnortConfig *, const void *, const void *, int);
693 +typedef int (*PCRE2OvectorSizeFunc)(void);
694 +typedef void *(*PCRE2MatchDataCreateFunc)(int, const void *);
695 +typedef unsigned int (*PCRE2GetOvectorCountFunc)(const void *);
696 +typedef void *(*PCRE2GetOvectorPointerFunc)(const void *);
697 +typedef int (*PCRE2MatchRealFunc)(const void *, const char *, int, int, int, const void *, const void *);
698 +typedef void (*PCRE2MatchDataFreeFunc)(const void *);
699 +typedef void (*PCRE2MatchContextFreeFunc)(const void *);
700 +typedef void (*PCRE2CodeFreeFunc)(const void *);
701 +typedef void (*PCRE2Capture)(struct _SnortConfig *, const void *);
703 typedef struct _DynamicEngineData
705 @@ -175,9 +182,15 @@ typedef struct _DynamicEngineData
709 - PCRECompileFunc pcreCompile;
710 - PCREStudyFunc pcreStudy;
711 - PCREExecFunc pcreExec;
712 + PCRE2CompileFunc pcre2Compile;
713 + PCRE2MatchContextCreate pcre2MatchContextCreate;
714 + PCRE2JITCompileFunc pcre2JITCompile;
715 + PCRE2OvectorSizeFunc pcre2OvectorSize;
716 + PCRE2MatchDataCreateFunc pcre2MatchDataCreate;
717 + PCRE2GetOvectorCountFunc pcre2GetOvectorCount;
718 + PCRE2GetOvectorPointerFunc pcre2GetOvectorPointer;
719 + PCRE2MatchRealFunc pcre2MatchReal;
720 + PCRE2MatchDataFreeFunc pcre2MatchDataFree;
722 SfBase64Decode sfbase64decode;
723 GetAltDetectFunc GetAltDetect;
724 @@ -190,8 +203,7 @@ typedef struct _DynamicEngineData
726 UnregisterBit flowbitUnregister;
728 - PCRECapture pcreCapture;
729 - PCREOvectorInfo pcreOvectorInfo;
730 + PCRE2Capture pcre2Capture;
732 GetHttpBufferFunc getHttpBuffer;
733 DynamicDecompressInitFunc decompressInit;
734 --- a/src/dynamic-plugins/sf_dynamic_plugins.c
735 +++ b/src/dynamic-plugins/sf_dynamic_plugins.c
736 @@ -92,7 +92,8 @@ typedef HANDLE PluginHandle;
738 #include "fpdetect.h"
739 #include "sfportobject.h"
741 +#define PCRE2_CODE_UNIT_WIDTH 8
744 #include "event_wrapper.h"
746 @@ -1250,46 +1251,35 @@ void DynamicGetRuleData(void *p, const R
750 -void *pcreCompile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr)
751 +void *pcre2Compile(const char *pattern, int options, int *errorcode, size_t *erroffset, void *compilecontect)
753 options &= ~SNORT_PCRE_OVERRIDE_MATCH_LIMIT;
754 - return (void *)pcre_compile(pattern, options, errptr, erroffset, tableptr);
755 + return (void *)pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, options, errorcode, (PCRE2_SIZE *)erroffset, (pcre2_compile_context *)compilecontect);
758 -void *pcreStudy(struct _SnortConfig *sc, const void *code, int options, const char **errptr)
759 +void *pcre2MatchContextCreate(const void *generalcontext)
761 + return (void *)pcre2_match_context_create((pcre2_general_context *)generalcontext);
764 +int pcre2JITCompile(struct _SnortConfig *sc, const void *code, const void *matchcontext, int options)
766 - pcre_extra *extra_extra;
767 int snort_options = options & SNORT_PCRE_OVERRIDE_MATCH_LIMIT;
770 - extra_extra = pcre_study((const pcre*)code, 0, errptr);
771 + errorcode = pcre2_jit_compile((pcre2_code*)code, PCRE2_JIT_COMPLETE);
776 if ((ScPcreMatchLimitNewConf(sc) != -1) && !(snort_options & SNORT_PCRE_OVERRIDE_MATCH_LIMIT))
778 - if (extra_extra->flags & PCRE_EXTRA_MATCH_LIMIT)
780 - extra_extra->match_limit = ScPcreMatchLimitNewConf(sc);
784 - extra_extra->flags |= PCRE_EXTRA_MATCH_LIMIT;
785 - extra_extra->match_limit = ScPcreMatchLimitNewConf(sc);
787 + pcre2_set_match_limit((pcre2_match_context*)matchcontext, ScPcreMatchLimitNewConf(sc));
790 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
791 if ((ScPcreMatchLimitRecursionNewConf(sc) != -1) && !(snort_options & SNORT_PCRE_OVERRIDE_MATCH_LIMIT))
793 - if (extra_extra->flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION)
795 - extra_extra->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
799 - extra_extra->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
800 - extra_extra->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
802 + pcre2_set_depth_limit((pcre2_match_context*)matchcontext, ScPcreMatchLimitRecursionNewConf(sc));
806 @@ -1298,40 +1288,62 @@ void *pcreStudy(struct _SnortConfig *sc,
807 if (!(snort_options & SNORT_PCRE_OVERRIDE_MATCH_LIMIT) &&
808 ((ScPcreMatchLimitNewConf(sc) != -1) || (ScPcreMatchLimitRecursionNewConf(sc) != -1)))
810 - extra_extra = (pcre_extra *)SnortAlloc(sizeof(pcre_extra));
811 if (ScPcreMatchLimitNewConf(sc) != -1)
813 - extra_extra->flags |= PCRE_EXTRA_MATCH_LIMIT;
814 - extra_extra->match_limit = ScPcreMatchLimitNewConf(sc);
815 + pcre2_set_match_limit((pcre2_match_context*)matchcontext, ScPcreMatchLimitNewConf(sc));
818 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
819 if (ScPcreMatchLimitRecursionNewConf(sc) != -1)
821 - extra_extra->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
822 - extra_extra->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
823 + pcre2_set_depth_limit((pcre2_match_context*)matchcontext, ScPcreMatchLimitRecursionNewConf(sc));
829 - return extra_extra;
833 +int pcre2OvectorSize(void)
835 + return snort_conf->pcre_ovector_size;
838 +void *pcre2MatchDataCreate(int size, const void *generalcontext)
840 + return pcre2_match_data_create(size, (pcre2_general_context *)generalcontext);
843 +unsigned int pcre2GetOvectorCount(const void *match_data)
845 + return pcre2_get_ovector_count((pcre2_match_data *)match_data);
848 +void *pcre2GetOvectorPointer(const void *match_data)
850 + return pcre2_get_ovector_pointer((pcre2_match_data *)match_data);
853 +int pcre2MatchReal(const void *code, const char *subj,
854 + int len, int start, int options, const void *matchdata, const void *matchcontext)
856 + return pcre2_match((const pcre2_code *)code, (PCRE2_SPTR)subj, len, start, options, (pcre2_match_data *)matchdata, (pcre2_match_context *)matchcontext);
859 +void pcre2MatchDataFree(const void *match_data)
861 + pcre2_match_data_free((pcre2_match_data *)match_data);
866 - * Get the Ovector configuration for PCRE from the snort.conf
868 -void pcreOvectorInfo(int **ovector, int *ovector_size)
869 +void pcre2MatchContextFree(const void *code)
871 - *ovector = snort_conf->pcre_ovector;
872 - *ovector_size = snort_conf->pcre_ovector_size;
873 + pcre2_match_context_free((pcre2_match_context *)code);
876 -int pcreExec(const void *code, const void *extra, const char *subj,
877 - int len, int start, int options, int *ovec, int ovecsize)
878 +void pcre2CodeFree(const void *code)
880 - return pcre_exec((const pcre *)code, (const pcre_extra *)extra, subj, len, start, options, ovec, ovecsize);
881 + pcre2_code_free((pcre2_code *)code);
884 static int setFlowId(const void* p, uint32_t id)
885 @@ -1415,17 +1427,22 @@ int InitDynamicEngines(char *dynamic_rul
886 engineData.debugMsgLine = &no_line;
889 - engineData.pcreStudy = &pcreStudy;
890 - engineData.pcreCompile = &pcreCompile;
891 - engineData.pcreExec = &pcreExec;
892 + engineData.pcre2JITCompile = &pcre2JITCompile;
893 + engineData.pcre2MatchContextCreate = &pcre2MatchContextCreate;
894 + engineData.pcre2Compile = &pcre2Compile;
895 + engineData.pcre2OvectorSize = &pcre2OvectorSize;
896 + engineData.pcre2MatchDataCreate = &pcre2MatchDataCreate;
897 + engineData.pcre2GetOvectorCount = &pcre2GetOvectorCount;
898 + engineData.pcre2GetOvectorPointer = &pcre2GetOvectorPointer;
899 + engineData.pcre2MatchReal = &pcre2MatchReal;
900 + engineData.pcre2MatchDataFree = &pcre2MatchDataFree;
902 engineData.allocRuleData = &DynamicRuleDataAlloc;
903 engineData.freeRuleData = &DynamicRuleDataFree;
905 engineData.flowbitUnregister = &DynamicFlowbitUnregister;
907 - engineData.pcreCapture = &PcreCapture;
908 - engineData.pcreOvectorInfo = &pcreOvectorInfo;
909 + engineData.pcre2Capture = &Pcre2Capture;
910 engineData.getHttpBuffer = getHttpBuffer;
912 engineData.decompressInit = &DynamicDecompressInit;
913 --- a/src/dynamic-plugins/sf_engine/examples/3036.c
914 +++ b/src/dynamic-plugins/sf_engine/examples/3036.c
915 @@ -104,7 +104,7 @@ static RuleOption rule3036option3 =
916 { &rule3036byte_test3 }
918 // pcre:"^.{27}", relative;
919 -static PCREInfo rule3036pcre4 =
920 +static PCRE2Info rule3036pcre4 =
922 "^.{27}", /* pattern */
923 NULL, /* holder for compiled pattern */
924 @@ -166,7 +166,7 @@ static RuleOption rule3036option6 =
925 { &rule3036byte_jump6 }
927 // pcre:"^.{4}", relative;
928 -static PCREInfo rule3036pcre7 =
929 +static PCRE2Info rule3036pcre7 =
931 "^.{4}", /* pattern */
932 NULL, /* holder for compiled pattern */
933 @@ -325,13 +325,13 @@ int rule3036eval(void *p) {
934 // byte_test:size 1, value 128, operator &, offset 6, relative;
935 if (byteTest(p, rule3036options[3]->option_u.byte, cursor_normal) > 0) {
936 // pcre:"^.{27}", relative;
937 - if (pcreMatch(p, rule3036options[4]->option_u.pcre, &cursor_normal)) {
938 + if (pcre2Match(p, rule3036options[4]->option_u.pcre2, &cursor_normal)) {
939 // content:"|01 00|", offset 37, depth 2, relative;
940 if (contentMatch(p, rule3036options[5]->option_u.content, &cursor_normal) > 0) {
941 // byte_jump:size 4, offset -7, relative, endian little;
942 if (byteJump(p, rule3036options[6]->option_u.byte, &cursor_normal) > 0) {
943 // pcre:"^.{4}", relative;
944 - if (pcreMatch(p, rule3036options[7]->option_u.pcre, &cursor_normal)) {
945 + if (pcre2Match(p, rule3036options[7]->option_u.pcre2, &cursor_normal)) {
946 // content:"|00 00 00 00|", offset 16, depth 4, relative;
947 if (!(contentMatch(p, rule3036options[8]->option_u.content, &cursor_normal) > 0)) {
948 // byte_jump:size 4, offset 16, relative, endian little;
949 --- a/src/dynamic-plugins/sf_engine/examples/3052.c
950 +++ b/src/dynamic-plugins/sf_engine/examples/3052.c
951 @@ -93,7 +93,7 @@ static RuleOption rule3052option2 =
952 { &rule3052byte_test2 }
954 // pcre:"^.{27}", relative;
955 -static PCREInfo rule3052pcre3 =
956 +static PCRE2Info rule3052pcre3 =
958 "^.{27}", /* pattern */
959 NULL, /* holder for compiled pattern */
960 @@ -155,7 +155,7 @@ static RuleOption rule3052option5 =
961 { &rule3052byte_jump5 }
963 // pcre:"^.{4}", relative;
964 -static PCREInfo rule3052pcre6 =
965 +static PCRE2Info rule3052pcre6 =
967 "^.{4}", /* pattern */
968 NULL, /* holder for compiled pattern */
969 @@ -307,13 +307,13 @@ int rule3052eval(void *p) {
970 // byte_test:size 1, value 128, operator &, offset 6, relative;
971 if (byteTest(p, rule3052options[2]->option_u.byte, cursor_normal) > 0) {
972 // pcre:"^.{27}", relative;
973 - if (pcreMatch(p, rule3052options[3]->option_u.pcre, &cursor_normal)) {
974 + if (pcre2Match(p, rule3052options[3]->option_u.pcre2, &cursor_normal)) {
975 // content:"|01 00|", offset 37, depth 2, relative;
976 if (contentMatch(p, rule3052options[4]->option_u.content, &cursor_normal) > 0) {
977 // byte_jump:size 4, offset -7, relative, endian little;
978 if (byteJump(p, rule3052options[5]->option_u.byte, &cursor_normal) > 0) {
979 // pcre:"^.{4}", relative;
980 - if (pcreMatch(p, rule3052options[6]->option_u.pcre, &cursor_normal)) {
981 + if (pcre2Match(p, rule3052options[6]->option_u.pcre2, &cursor_normal)) {
982 // content:"|00 00 00 00|", offset 16, depth 4, relative;
983 if (!(contentMatch(p, rule3052options[7]->option_u.content, &cursor_normal) > 0)) {
984 // byte_jump:size 4, offset 16, relative, endian little;
985 --- a/src/dynamic-plugins/sf_engine/examples/3099.c
986 +++ b/src/dynamic-plugins/sf_engine/examples/3099.c
987 @@ -104,7 +104,7 @@ static RuleOption rule3099option3 =
988 { &rule3099byte_test3 }
990 // pcre:"^.{27}", relative;
991 -static PCREInfo rule3099pcre4 =
992 +static PCRE2Info rule3099pcre4 =
994 "^.{27}", /* pattern */
995 NULL, /* holder for compiled pattern */
996 @@ -191,7 +191,7 @@ static RuleOption rule3099option7 =
997 { &rule3099byte_jump7 }
999 // pcre:"^.{4}", relative;
1000 -static PCREInfo rule3099pcre8 =
1001 +static PCRE2Info rule3099pcre8 =
1003 "^.{4}", /* pattern */
1004 NULL, /* holder for compiled pattern */
1005 @@ -392,7 +392,7 @@ int rule3099eval(void *p) {
1006 // byte_test:size 1, value 128, operator &, offset 6, relative;
1007 if (!(byteTest(p, rule3099options[3]->option_u.byte, cursor_normal) > 0)) {
1008 // pcre:"^.{27}", relative;
1009 - if (pcreMatch(p, rule3099options[4]->option_u.pcre, &cursor_normal)) {
1010 + if (pcre2Match(p, rule3099options[4]->option_u.pcre2, &cursor_normal)) {
1011 // content:"&|00|", offset 29, depth 2, relative;
1012 if (contentMatch(p, rule3099options[5]->option_u.content, &cursor_normal) > 0) {
1013 // content:"|5C|PIPE|5C 00|", offset 4, nocase, relative;
1014 @@ -400,7 +400,7 @@ int rule3099eval(void *p) {
1015 // byte_jump:size 2, offset -17, relative, endian little;
1016 if (byteJump(p, rule3099options[7]->option_u.byte, &cursor_normal) > 0) {
1017 // pcre:"^.{4}", relative;
1018 - if (pcreMatch(p, rule3099options[8]->option_u.pcre, &cursor_normal)) {
1019 + if (pcre2Match(p, rule3099options[8]->option_u.pcre2, &cursor_normal)) {
1020 // content:"|05|", depth 1, relative;
1021 if (contentMatch(p, rule3099options[9]->option_u.content, &cursor_normal) > 0) {
1022 // byte_test:size 1, value 16, operator &, offset 3, relative;
1023 --- a/src/dynamic-plugins/sf_engine/examples/36733.c
1024 +++ b/src/dynamic-plugins/sf_engine/examples/36733.c
1030 +#define PCRE2_CODE_UNIT_WIDTH 8
1032 #include "sf_snort_plugin_api.h"
1033 #include "sf_snort_packet.h"
1034 #include "web-misc_base64_decode.h"
1035 @@ -80,12 +81,12 @@ static RuleOption ruleAPACHEAUTHLDAPopti
1038 // pcre:"/^Authorization:\s*Basic/mi";
1039 -static PCREInfo ruleAPACHEAUTHLDAPpcre0 =
1040 +static PCRE2Info ruleAPACHEAUTHLDAPpcre0 =
1042 "^Authorization:\\s*Basic\\s+", /* pattern (now in snort content format) */
1043 0, /* compiled expression */
1044 0, /* compiled extra */
1045 - PCRE_CASELESS | PCRE_MULTILINE, /* compile flags */
1046 + PCRE2_CASELESS | PCRE2_MULTILINE, /* compile flags */
1047 CONTENT_BUF_NORMALIZED, /* flags */ // XXX - need to add CONTENT_FAST_PATTERN support
1050 @@ -99,7 +100,7 @@ static RuleOption ruleAPACHEAUTHLDAPopti
1053 // pcre:"/%[0-9]*\.?[0-9]*[:formatspecifiers:]/";
1054 -static PCREInfo ruleAPACHEAUTHLDAPpcre1 =
1055 +static PCRE2Info ruleAPACHEAUTHLDAPpcre1 =
1057 // "%[-# +'I]*[0-9]*\\.?[0-9]*[qjzthdiouxefgcrslnp]", /* pattern (now in snort content format) */ // ZDNOTE
1058 "%.+%.", /* regex. The above is technically more correct, but this is faster and good enough */
1059 @@ -191,7 +192,7 @@ static int ruleAPACHEAUTHLDAPeval(void *
1061 // manual pcre stuff
1063 - int ovector[3]; // Needs to be a multiple of 3
1067 return RULE_NOMATCH;
1068 @@ -221,7 +222,7 @@ static int ruleAPACHEAUTHLDAPeval(void *
1069 //DEBUG_WRAP(printf("found content:\"Authorization:\" %p\n", cursor));
1071 // pcre:"/^Authorization:\s*Basic\s+/mi"
1072 - if(pcreMatch(p, ruleAPACHEAUTHLDAPoptions[2]->option_u.pcre, &cursor) <= 0)
1073 + if(pcre2Match(p, ruleAPACHEAUTHLDAPoptions[2]->option_u.pcre2, &cursor) <= 0)
1074 return RULE_NOMATCH;
1076 //DEBUG_WRAP(printf("found pcre:\"/^Authorization:\\s*Basic\\s+/mi\" %p\n", cursor));
1077 @@ -238,14 +239,35 @@ static int ruleAPACHEAUTHLDAPeval(void *
1079 //DEBUG_WRAP(printf("Successfully base64 decoded (%s)(%d)\n", decodedbuf, decodedbytes));
1081 + match_data = pcre2MatchDataCreateWrapper();
1083 + return RULE_NOMATCH;
1085 // Now run our regex on the base64 decoding to find an attack
1086 - result = pcreExecWrapper(ruleAPACHEAUTHLDAPoptions[3]->option_u.pcre,
1087 + result = pcre2MatchWrapper(ruleAPACHEAUTHLDAPoptions[3]->option_u.pcre2,
1088 (char *)decodedbuf, // subject string
1089 decodedbytes, // subject length
1091 0, // options (handled at compile time)
1092 - ovector, // ovector for storing result substrings
1093 - sizeof(ovector)/sizeof(int)); // size of ovector
1094 + match_data); // size of ovector
1096 + /* If ovector is required:
1097 + * 1. declare a size_t *ovector
1098 + * 2. after pcre2ExecWrapper...
1099 + * 3. ovector = pcre2GetOvectorPointer(match_data);
1100 + * 4. Use ovector as old implementation
1102 + * If required ovector_size:
1103 + * 1. declare a unsigned int ovector_size
1104 + * 2. after pcre2ExecWrapper...
1105 + * 3. ovector_size = pcre2GetOvectorCount(match_data);
1106 + * 4. User ovector_size as old implementation
1108 + * ALWAYS REMEMBER TO USE THE MATCH DATA CREATE AND FREE BEFORE
1112 + pcre2MatchDataFreeWrapper(match_data);
1114 //DEBUG_WRAP(printf("result = %d\n", result));
1116 --- a/src/dynamic-plugins/sf_engine/examples/3682.c
1117 +++ b/src/dynamic-plugins/sf_engine/examples/3682.c
1123 +#define PCRE2_CODE_UNIT_WIDTH 8
1125 #include "sf_snort_plugin_api.h"
1126 #include "sf_snort_packet.h"
1127 #include "detection_lib_meta.h"
1128 @@ -103,12 +104,12 @@ static RuleOption rule3682option3 =
1130 /* pcre for sid 3682 */
1131 //pcre:"/Content-Type\x3A\s+audio\/(x-wav|mpeg|x-midi)/i";
1132 -static PCREInfo rule3682pcre4 =
1133 +static PCRE2Info rule3682pcre4 =
1135 "Content-Type\\x3A\\s+audio\\/(x-wav|mpeg|x-midi)", /* expression */
1136 NULL, /* Holder for compiled expr */
1137 NULL, /* Holder for compiled expr extra flags */
1138 - PCRE_CASELESS, /* Compile Flags */
1139 + PCRE2_CASELESS, /* Compile Flags */
1140 CONTENT_BUF_NORMALIZED, /* Flags */
1143 @@ -148,12 +149,12 @@ static RuleOption rule3682option5 =
1145 /* pcre for sid 3682 */
1146 //pcre:"/filename=[\x22\x27]?.{1,221}\.(vbs|exe|scr|pif|bat)/i";
1147 -static PCREInfo rule3682pcre6 =
1148 +static PCRE2Info rule3682pcre6 =
1150 "filename=[\\x22\\x27]?.{1,221}\\.(vbs|exe|scr|pif|bat)", /* expression */
1151 NULL, /* Holder for compiled expr */
1152 NULL, /* Holder for compiled expr extra flags */
1153 - PCRE_CASELESS, /* Compile Flags */
1154 + PCRE2_CASELESS, /* Compile Flags */
1155 CONTENT_BUF_NORMALIZED, /* Flags */
1158 --- a/src/dynamic-plugins/sf_engine/examples/bug31842.c
1159 +++ b/src/dynamic-plugins/sf_engine/examples/bug31842.c
1165 +#define PCRE2_CODE_UNIT_WIDTH 8
1167 #include "sf_snort_plugin_api.h"
1168 #include "sf_snort_packet.h"
1170 @@ -89,12 +90,12 @@ static RuleOption ruleSQUID_NTLM_AUTHopt
1174 -static PCREInfo ruleSQUID_NTLM_AUTHpcre =
1175 +static PCRE2Info ruleSQUID_NTLM_AUTHpcre =
1177 "^Proxy-Authorization:\\s*NTLM\\s+", /* pattern to search for */
1178 NULL, /* holder for compiled pattern */
1179 NULL, /* holder for compiled pattern flags */
1180 - PCRE_CASELESS | PCRE_DOTALL | PCRE_MULTILINE, /* compile flags */
1181 + PCRE2_CASELESS | PCRE2_DOTALL | PCRE2_MULTILINE, /* compile flags */
1182 CONTENT_BUF_NORMALIZED, /* content flags */
1185 @@ -336,7 +337,7 @@ int ruleSQUID_NTLM_AUTHeval(void *p) {
1188 /* call pcre match */
1189 - if (pcreMatch(p, ruleSQUID_NTLM_AUTHoptions[2]->option_u.pcre, &cursor) <= 0) {
1190 + if (pcre2Match(p, ruleSQUID_NTLM_AUTHoptions[2]->option_u.pcre2, &cursor) <= 0) {
1191 return RULE_NOMATCH;
1194 --- a/src/dynamic-plugins/sf_engine/examples/bug35218.c
1195 +++ b/src/dynamic-plugins/sf_engine/examples/bug35218.c
1201 +#define PCRE2_CODE_UNIT_WIDTH 8
1203 #include "sf_snort_plugin_api.h"
1204 #include "sf_snort_packet.h"
1206 @@ -97,12 +98,12 @@ static RuleOption ruleEXCHANGE_BASE64_DE
1210 -static PCREInfo ruleEXCHANGE_BASE64_DECODEpcre0 =
1211 +static PCRE2Info ruleEXCHANGE_BASE64_DECODEpcre0 =
1213 "^Content-Transfer-Encoding:\\s*base64\\s*$", /* pattern to search for */
1214 NULL, /* compiled_expr */
1215 0, /* compiled_extra */
1216 - PCRE_CASELESS | PCRE_MULTILINE, /* compile_flags */
1217 + PCRE2_CASELESS | PCRE2_MULTILINE, /* compile_flags */
1218 CONTENT_BUF_RAW, /* flags: must include a CONTENT_BUF_X */
1221 @@ -119,12 +120,12 @@ static RuleOption ruleEXCHANGE_BASE64_DE
1222 /* Second PCRE just like above but with CONTENT_RELATIVE so we can find
1223 additional base64 sections if they exist.
1225 -static PCREInfo ruleEXCHANGE_BASE64_DECODEpcre1 =
1226 +static PCRE2Info ruleEXCHANGE_BASE64_DECODEpcre1 =
1228 "^Content-Transfer-Encoding:\\s*base64\\s*$", /* pattern to search for */
1229 NULL, /* compiled_expr */
1230 0, /* compiled_extra */
1231 - PCRE_CASELESS | PCRE_MULTILINE, /* compile_flags */
1232 + PCRE2_CASELESS | PCRE2_MULTILINE, /* compile_flags */
1233 CONTENT_BUF_RAW | CONTENT_RELATIVE, /* flags: must include a CONTENT_BUF_X */
1236 @@ -214,7 +215,7 @@ int ruleEXCHANGE_BASE64_DECODEeval(void
1239 /* call pcre match */
1240 - if (pcreMatch(sp, ruleEXCHANGE_BASE64_DECODEoptions[2]->option_u.pcre, &cursor_normal) <= 0) {
1241 + if (pcre2Match(sp, ruleEXCHANGE_BASE64_DECODEoptions[2]->option_u.pcre2, &cursor_normal) <= 0) {
1242 return RULE_NOMATCH;
1245 @@ -286,7 +287,7 @@ int ruleEXCHANGE_BASE64_DECODEeval(void
1247 } else { /* !in_base64_content */
1248 // Find the next base64 content the easy way
1249 - if(pcreMatch(sp, ruleEXCHANGE_BASE64_DECODEoptions[3]->option_u.pcre, &cursor_normal) <= 0)
1250 + if(pcre2Match(sp, ruleEXCHANGE_BASE64_DECODEoptions[3]->option_u.pcre2, &cursor_normal) <= 0)
1251 return RULE_NOMATCH;
1253 // Another base64 section was found, set up for another loop
1254 --- a/src/dynamic-plugins/sf_engine/examples/sid1902.c
1255 +++ b/src/dynamic-plugins/sf_engine/examples/sid1902.c
1261 +#define PCRE2_CODE_UNIT_WIDTH 8
1263 #include "sf_snort_plugin_api.h"
1264 #include "sf_snort_packet.h"
1266 @@ -59,12 +60,12 @@ static RuleOption rule1902option1 =
1267 { &rule1902content1 }
1269 // pcre:"\sLSUB\s[^\n]*?\s\{", dotall, multiline, nocase;
1270 -static PCREInfo rule1902pcre2 =
1271 +static PCRE2Info rule1902pcre2 =
1273 "\\sLSUB\\s[^\\n]*?\\s\\{", /* pattern */
1274 NULL, /* holder for compiled pattern */
1275 NULL, /* holder for compiled pattern flags */
1276 - PCRE_CASELESS|PCRE_DOTALL|PCRE_MULTILINE, /* compile flags */
1277 + PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_MULTILINE, /* compile flags */
1278 CONTENT_BUF_NORMALIZED, /* content flags */
1281 @@ -177,7 +178,7 @@ int rule1902eval(void *p) {
1282 // content:"LSUB", nocase;
1283 if (contentMatch(p, rule1902options[1]->option_u.content, &cursor_normal) > 0) {
1284 // pcre:"\sLSUB\s[^\n]*?\s\{", dotall, multiline, nocase;
1285 - if (pcreMatch(p, rule1902options[2]->option_u.pcre, &cursor_normal)) {
1286 + if (pcre2Match(p, rule1902options[2]->option_u.pcre2, &cursor_normal)) {
1287 // byte_test:size 5, value 256, operator >, relative, representation dec;
1288 if (byteTest(p, rule1902options[3]->option_u.byte, cursor_normal) > 0) {
1290 --- a/src/dynamic-plugins/sf_engine/examples/sid2389.c
1291 +++ b/src/dynamic-plugins/sf_engine/examples/sid2389.c
1297 +#define PCRE2_CODE_UNIT_WIDTH 8
1299 #include "sf_snort_plugin_api.h"
1300 #include "detection_lib_meta.h"
1302 @@ -113,12 +114,12 @@ static RuleOption option2 =
1306 -static PCREInfo pcre1 =
1307 +static PCRE2Info pcre1 =
1309 "^RNTO\\s[^\\n]{100}", /* expression */
1310 NULL, /* Holder for compiled expr */
1311 NULL, /* Holder for compiled expr extra flags */
1312 - PCRE_DOTALL | PCRE_MULTILINE | PCRE_CASELESS, /* Compile Flags */
1313 + PCRE2_DOTALL | PCRE2_MULTILINE | PCRE2_CASELESS, /* Compile Flags */
1314 CONTENT_BUF_NORMALIZED, /* Flags */
1317 @@ -178,7 +179,7 @@ int sid2389Eval(void *p)
1318 if (contentMatch(p, sid2389.options[1]->option_u.content, &norm_cur)>0)
1320 /* Not relative to norm cursor */
1321 - if (pcreMatch(p, sid2389.options[2]->option_u.pcre, NULL))
1322 + if (pcre2Match(p, sid2389.options[2]->option_u.pcre2, NULL))
1326 --- a/src/dynamic-plugins/sf_engine/examples/sid9999.c
1327 +++ b/src/dynamic-plugins/sf_engine/examples/sid9999.c
1328 @@ -159,7 +159,7 @@ static CursorInfo loopCursor =
1329 /* these don't get structures... lets hope this works :) */
1330 /* pcre for sid 9999 */
1331 // pcre:"^[rbg]XYZ", relative;
1332 -static PCREInfo rule9999pcre7 =
1333 +static PCRE2Info rule9999pcre7 =
1335 "^[rbg]XYZ", /* pattern */
1336 NULL, /* holder for compiled pattern */
1337 --- a/src/dynamic-plugins/sf_engine/examples/web-client_test.c
1338 +++ b/src/dynamic-plugins/sf_engine/examples/web-client_test.c
1339 @@ -85,12 +85,12 @@ static RuleOption rule64111option1 =
1342 // pcre:"IIS 7\x2e5 Detailed Error - 404\x2e0 - Not Found", nocase;
1343 -static PCREInfo rule64111pcre2 =
1344 +static PCRE2Info rule64111pcre2 =
1346 "IIS 7\\x2e5 Detailed Error - 404\\x2e0 - Not Found", /* pattern */
1347 NULL, /* holder for compiled pattern */
1348 NULL, /* holder for compiled pattern flags */
1349 - PCRE_CASELESS, /* compile flags */
1350 + PCRE2_CASELESS, /* compile flags */
1351 CONTENT_BUF_NORMALIZED, /* content flags */
1354 @@ -256,12 +256,12 @@ static RuleOption rule64222option2 =
1357 // pcre:"SignUrl=[^\x26\s]*[\x22\x27\x28\x29\x3C\x3E]", payload uri, nocase;
1358 -static PCREInfo rule64222pcre3 =
1359 +static PCRE2Info rule64222pcre3 =
1361 "SignUrl=[^\\x26\\s]*[\\x22\\x27\\x28\\x29\\x3C\\x3E]", /* pattern */
1362 NULL, /* holder for compiled pattern */
1363 NULL, /* holder for compiled pattern flags */
1364 - PCRE_CASELESS, /* compile flags */
1365 + PCRE2_CASELESS, /* compile flags */
1366 CONTENT_BUF_URI, /* content flags */
1369 @@ -428,12 +428,12 @@ static RuleOption rule64333option2 =
1372 // pcre:"SignUrl=[^\\x26\\s]*[\\x22\\x27\\x28\\x29\\x3C\\x3E]", payload uri, nocase;
1373 -static PCREInfo rule64333pcre3 =
1374 +static PCRE2Info rule64333pcre3 =
1376 "SignUrl=[^\\\\x26\\\\s]*[\\\\x22\\\\x27\\\\x28\\\\x29\\\\x3C\\\\x3E]", /* pattern */
1377 NULL, /* holder for compiled pattern */
1378 NULL, /* holder for compiled pattern flags */
1379 - PCRE_CASELESS, /* compile flags */
1380 + PCRE2_CASELESS, /* compile flags */
1381 CONTENT_BUF_URI, /* content flags */
1384 @@ -550,7 +550,7 @@ int rule64111eval(void *p) {
1385 // content:"IIS 7.5 Detailed Error - 404.0 - Not Found", depth 0, nocase, fast_pattern;
1386 if (contentMatch(p, rule64111options[1]->option_u.content, &cursor_normal) > 0) {
1387 // pcre:"IIS 7\x2e5 Detailed Error - 404\x2e0 - Not Found", nocase;
1388 - if (pcreMatch(p, rule64111options[2]->option_u.pcre, &cursor_normal)) {
1389 + if (pcre2Match(p, rule64111options[2]->option_u.pcre2, &cursor_normal)) {
1393 @@ -576,7 +576,7 @@ int rule64222eval(void *p) {
1394 // content:"SignUrl=", payload http_uri, depth 0, nocase;
1395 if (contentMatch(p, rule64222options[2]->option_u.content, &cursor_http_uri) > 0) {
1396 // pcre:"SignUrl=[^\x26\s]*[\x22\x27\x28\x29\x3C\x3E]", payload uri, nocase;
1397 - if (pcreMatch(p, rule64222options[3]->option_u.pcre, &cursor_uri)) {
1398 + if (pcre2Match(p, rule64222options[3]->option_u.pcre2, &cursor_uri)) {
1402 @@ -603,7 +603,7 @@ int rule64333eval(void *p) {
1403 // content:"SignUrl=", payload http_uri, depth 0, nocase;
1404 if (contentMatch(p, rule64333options[2]->option_u.content, &cursor_http_uri) > 0) {
1405 // pcre:"SignUrl=[^\\x26\\s]*[\\x22\\x27\\x28\\x29\\x3C\\x3E]", payload uri, nocase;
1406 - if (pcreMatch(p, rule64333options[3]->option_u.pcre, &cursor_uri)) {
1407 + if (pcre2Match(p, rule64333options[3]->option_u.pcre2, &cursor_uri)) {
1411 --- a/src/dynamic-plugins/sf_engine/sf_snort_detection_engine.c
1412 +++ b/src/dynamic-plugins/sf_engine/sf_snort_detection_engine.c
1413 @@ -899,11 +899,11 @@ int RegisterOneRule(struct _SnortConfig
1415 case OPTION_TYPE_PCRE:
1417 - PCREInfo *pcre = option->option_u.pcre;
1418 + PCRE2Info *pcre2 = option->option_u.pcre2;
1420 - if (pcre->compiled_expr == NULL)
1421 + if (pcre2->compiled_expr == NULL)
1423 - if (PCRESetup(sc, rule, pcre))
1424 + if (PCRE2Setup(sc, rule, pcre2))
1426 rule->initialized = 0;
1428 @@ -1120,18 +1120,18 @@ static void FreeOneRule(void *data)
1430 case OPTION_TYPE_PCRE:
1432 - PCREInfo *pcre = option->option_u.pcre;
1433 + PCRE2Info *pcre2 = option->option_u.pcre2;
1435 - if (pcre->compiled_expr != NULL)
1436 + if (pcre2->match_context != NULL)
1438 - free(pcre->compiled_expr);
1439 - pcre->compiled_expr = NULL;
1440 + pcre2_match_context_free(pcre2->match_context);
1441 + pcre2->match_context = NULL;
1444 - if (pcre->compiled_extra != NULL)
1445 + if (pcre2->compiled_expr != NULL)
1447 - free(pcre->compiled_extra);
1448 - pcre->compiled_extra = NULL;
1449 + pcre2_code_free(pcre2->compiled_expr);
1450 + pcre2->compiled_expr = NULL;
1454 --- a/src/dynamic-plugins/sf_engine/sf_snort_detection_engine.h
1455 +++ b/src/dynamic-plugins/sf_engine/sf_snort_detection_engine.h
1457 #define SF_SNORT_DETECTION_ENGINE__H
1459 int BoyerContentSetup(Rule *rule, ContentInfo *content);
1460 -int PCRESetup(struct _SnortConfig *sc, Rule *rule, PCREInfo *pcreInfo);
1461 +int PCRE2Setup(struct _SnortConfig *sc, Rule *rule, PCRE2Info *pcre2Info);
1462 int ValidateHeaderCheck(Rule *rule, HdrOptCheck *optData);
1463 void ContentSetup(void);
1464 int ByteExtractInitialize(Rule *rule, ByteExtract *extractData);
1465 --- a/src/dynamic-plugins/sf_engine/sf_snort_plugin_api.c
1466 +++ b/src/dynamic-plugins/sf_engine/sf_snort_plugin_api.c
1467 @@ -640,7 +640,7 @@ int isRelativeOption(RuleOption *option)
1468 relative = option->option_u.content->flags & CONTENT_RELATIVE;
1470 case OPTION_TYPE_PCRE:
1471 - relative = option->option_u.pcre->flags & CONTENT_RELATIVE;
1472 + relative = option->option_u.pcre2->flags & CONTENT_RELATIVE;
1474 case OPTION_TYPE_FLOWBIT:
1475 /* Never relative */
1476 @@ -716,7 +716,7 @@ int ruleMatchInternal(SFSnortPacket *p,
1477 int32_t origOffset = 0;
1478 uint32_t origDepth = 0;
1479 int continueLoop = 1;
1480 - PCREInfo *thisPCREInfo = NULL;
1481 + PCRE2Info *thisPCREInfo = NULL;
1484 startCursor = thisCursor = *cursor;
1485 @@ -736,7 +736,7 @@ int ruleMatchInternal(SFSnortPacket *p,
1486 origOffset = thisContentInfo->offset;
1488 case OPTION_TYPE_PCRE:
1489 - thisPCREInfo = rule->options[optIndex]->option_u.pcre;
1490 + thisPCREInfo = rule->options[optIndex]->option_u.pcre2;
1491 origFlags = thisPCREInfo->flags;
1492 origOffset = thisPCREInfo->offset;
1494 @@ -760,8 +760,8 @@ int ruleMatchInternal(SFSnortPacket *p,
1495 notFlag = rule->options[optIndex]->option_u.protectedContent->flags & NOT_FLAG;
1497 case OPTION_TYPE_PCRE:
1498 - retVal = pcreMatch(p, rule->options[optIndex]->option_u.pcre, &thisCursor);
1499 - notFlag = rule->options[optIndex]->option_u.pcre->flags & NOT_FLAG;
1500 + retVal = pcre2Match(p, rule->options[optIndex]->option_u.pcre2, &thisCursor);
1501 + notFlag = rule->options[optIndex]->option_u.pcre2->flags & NOT_FLAG;
1503 case OPTION_TYPE_FLOWBIT:
1504 retVal = processFlowbits(p, rule->options[optIndex]->option_u.flowBit);
1505 --- a/src/dynamic-plugins/sf_engine/sf_snort_plugin_api.h
1506 +++ b/src/dynamic-plugins/sf_engine/sf_snort_plugin_api.h
1508 #ifndef SF_SNORT_PLUGIN_API_H_
1509 #define SF_SNORT_PLUGIN_API_H_
1512 +#define PCRE2_CODE_UNIT_WIDTH 8
1517 @@ -211,26 +212,26 @@ typedef struct _CursorInfo
1521 -pcre.h provides flags:
1522 +pcre2.h provides flags:
1529 -PCRE_DOLLAR_ENDONLY
1536 +PCRE2_DOLLAR_ENDONLY
1540 -typedef struct _PCREInfo
1541 +typedef struct _PCRE2Info
1544 void *compiled_expr;
1545 - void *compiled_extra;
1546 + void *match_context;
1547 uint32_t compile_flags;
1548 uint32_t flags; /* must include a CONTENT_BUF_X */
1553 #define FLOWBIT_SET 0x01
1554 #define FLOWBIT_UNSET 0x02
1555 @@ -393,7 +394,7 @@ typedef struct _RuleOption
1556 ContentInfo *content;
1557 ProtectedContentInfo *protectedContent;
1561 FlowBitsInfo *flowBit;
1563 ByteExtract *byteExtract;
1564 @@ -482,7 +483,7 @@ ENGINE_LINKAGE int byteTest(void *p, Byt
1565 ENGINE_LINKAGE int byteMath(void *p, ByteData *byteData, const uint8_t *cursor);
1566 /* Same as extractValue plus setCursor */
1567 ENGINE_LINKAGE int byteJump(void *p, ByteData *byteData, const uint8_t **cursor);
1568 -ENGINE_LINKAGE int pcreMatch(void *p, PCREInfo* pcre, const uint8_t **cursor);
1569 +ENGINE_LINKAGE int pcre2Match(void *p, PCRE2Info* pcre2, const uint8_t **cursor);
1570 ENGINE_LINKAGE int detectAsn1(void *p, Asn1Context* asn1, const uint8_t *cursor);
1571 ENGINE_LINKAGE int checkHdrOpt(void *p, HdrOptCheck *optData);
1572 ENGINE_LINKAGE int loopEval(void *p, LoopInfo *loop, const uint8_t **cursor);
1573 @@ -506,8 +507,12 @@ ENGINE_LINKAGE void detectFlagDisable(SF
1574 ENGINE_LINKAGE int getAltDetect(uint8_t **bufPtr, uint16_t *altLenPtr);
1575 ENGINE_LINKAGE void setAltDetect(uint8_t *buf, uint16_t altLen);
1577 -ENGINE_LINKAGE int pcreExecWrapper(const PCREInfo *pcre_info, const char *buf, int len, int start_offset,
1578 - int options, int *ovector, int ovecsize);
1579 +ENGINE_LINKAGE void *pcre2MatchDataCreateWrapper(void);
1580 +ENGINE_LINKAGE void pcre2MatchDataFreeWrapper(void *match_data);
1581 +ENGINE_LINKAGE int pcre2GetOvectorCountWrapper(void *match_data);
1582 +ENGINE_LINKAGE void *pcre2GetOvectorPointerWrapper(void *match_data);
1583 +ENGINE_LINKAGE int pcre2MatchWrapper(const PCRE2Info *pcre2_info, const char *buf, int len, int start_offset,
1584 + int options, const void *match_data);
1586 static inline int invertMatchResult(int retVal)
1588 --- a/src/dynamic-plugins/sf_engine/sf_snort_plugin_pcre.c
1589 +++ b/src/dynamic-plugins/sf_engine/sf_snort_plugin_pcre.c
1594 - * PCRE operations for dynamic rule engine
1595 + * PCRE2 operations for dynamic rule engine
1597 #ifdef HAVE_CONFIG_H
1602 +#define PCRE2_CODE_UNIT_WIDTH 8
1604 #include "sf_types.h"
1605 #include "snort_debug.h"
1606 #include "sf_dynamic_define.h"
1608 /* Need access to the snort-isms that were passed to the engine */
1609 extern int checkCursorSimple(const uint8_t *cursor, int flags, const uint8_t *start, const uint8_t *end, int offset);
1610 extern int checkCursorInternal(void *p, int flags, int offset, const uint8_t *cursor);
1611 -static int pcreMatchInternal(void *, PCREInfo*, const uint8_t **);
1612 +static int pcreMatchInternal(void *, PCRE2Info*, const uint8_t **);
1614 -int PCRESetup(struct _SnortConfig *sc, Rule *rule, PCREInfo *pcreInfo)
1615 +int PCRE2Setup(struct _SnortConfig *sc, Rule *rule, PCRE2Info *pcre2Info)
1617 - const char *error;
1622 - pcreInfo->compiled_expr = (void *)_ded.pcreCompile(pcreInfo->expr,
1623 - pcreInfo->compile_flags,
1625 + pcre2Info->compiled_expr = (void *)_ded.pcre2Compile(pcre2Info->expr,
1626 + pcre2Info->compile_flags,
1631 - if (!pcreInfo->compiled_expr)
1632 + if (!pcre2Info->compiled_expr)
1634 /* error doing compilation. */
1635 - _ded.errMsg("Failed to compile PCRE in dynamic rule [%d:%d]\n",
1636 + _ded.errMsg("Failed to compile PCRE2 in dynamic rule [%d:%d]\n",
1637 rule->info.genID, rule->info.sigID);
1642 + pcre2Info->match_context = _ded.pcre2MatchContextCreate(NULL);
1643 + if (!pcre2Info->match_context)
1645 - pcreInfo->compiled_extra = (void *)_ded.pcreStudy(sc, pcreInfo->compiled_expr, pcreInfo->compile_flags, &error);
1646 + /* error doing match context */
1647 + _ded.errMsg("Failed to allocate mem for PCRE2 match context [%d:%d]\n",
1648 + rule->info.genID, rule->info.sigID);
1653 + errorcode = _ded.pcre2JITCompile(sc, pcre2Info->compiled_expr, pcre2Info->match_context, pcre2Info->compile_flags);
1656 /* error doing study. */
1657 _ded.errMsg("Failed to study PCRE in dynamic rule [%d:%d]\n",
1658 @@ -76,51 +83,82 @@ int PCRESetup(struct _SnortConfig *sc, R
1662 - _ded.pcreCapture(sc, pcreInfo->compiled_expr, pcreInfo->compiled_extra);
1663 + _ded.pcre2Capture(sc, pcre2Info->compiled_expr);
1670 - * * Wrapper for pcre_exec to expose ovector.
1671 + * * Wrapper for pcre2_match_data_create to run match_data.
1673 +ENGINE_LINKAGE void *pcre2MatchDataCreateWrapper(void)
1675 + return _ded.pcre2MatchDataCreate(_ded.pcre2OvectorSize(), NULL);
1679 + * * Wrapper for pcre2_match_data_free to run match_data.
1681 +ENGINE_LINKAGE void pcre2MatchDataFreeWrapper(void *match_data)
1683 + _ded.pcre2MatchDataFree(match_data);
1687 + * * Wrapper for pcre2_get_ovector_count to run match_data.
1689 +ENGINE_LINKAGE int pcre2GetOvectorCountWrapper(void *match_data)
1691 + return _ded.pcre2GetOvectorCount(match_data);
1695 + * * Wrapper for pcre2_get_ovector_pointer to run match_data.
1697 -ENGINE_LINKAGE int pcreExecWrapper(const PCREInfo *pcre_info, const char *buf, int len, int start_offset,
1698 - int options, int *ovector, int ovecsize)
1699 +ENGINE_LINKAGE void *pcre2GetOvectorPointerWrapper(void *match_data)
1701 + return _ded.pcre2GetOvectorPointer(match_data);
1705 + * * Wrapper for pcre2_match to run match_data.
1707 +ENGINE_LINKAGE int pcre2ExecWrapper(const PCRE2Info *pcre2_info, const char *buf, int len, int start_offset,
1708 + int options, const void *match_data)
1713 - if(pcre_info == NULL
1714 + if(pcre2_info == NULL
1718 || start_offset >= len
1719 - || ovector == NULL)
1720 + || match_data == NULL)
1725 - result = _ded.pcreExec(pcre_info->compiled_expr, /* result of pcre_compile() */
1726 - pcre_info->compiled_extra, /* result of pcre_study() */
1727 + result = _ded.pcre2MatchReal(pcre2_info->compiled_expr, /* result of pcre_compile() */
1728 buf, /* the subject string */
1729 len, /* the length of the subject string */
1730 start_offset, /* start at offset 0 in the subject */
1731 options, /* options(handled at compile time */
1732 - ovector, /* vector for substring information */
1733 - ovecsize); /* number of elements in the vector */
1734 + match_data, /* match_data for results */
1735 + pcre2_info->match_context); /* match_context for JIT limits */
1741 - else if(result == PCRE_ERROR_NOMATCH)
1742 + else if(result == PCRE2_ERROR_NOMATCH)
1748 - DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_exec error : %d \n", result););
1749 + DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_match error : %d \n", result););
1753 @@ -128,7 +166,7 @@ ENGINE_LINKAGE int pcreExecWrapper(const
1757 - * we need to specify the vector length for our pcre_exec call. we only care
1758 + * we need to specify the vector length for our pcre2_match call. we only care
1759 * about the first vector, which if the match is successful will include the
1760 * offset to the end of the full pattern match. If we decide to store other
1761 * matches, make *SURE* that this is a multiple of 3 as pcre requires it.
1762 @@ -136,7 +174,7 @@ ENGINE_LINKAGE int pcreExecWrapper(const
1763 #define SNORT_PCRE_OVECTOR_SIZE 3
1766 - * Perform a search of the PCRE data.
1767 + * Perform a search of the PCRE2 data.
1769 * @param pcre_data structure that options and patterns are passed in
1770 * @param buf buffer to search
1771 @@ -148,21 +186,18 @@ ENGINE_LINKAGE int pcreExecWrapper(const
1773 * @return 1 when we find the string, 0 when we don't (unless we've been passed a flag to invert)
1775 -static int pcre_test(const PCREInfo *pcre_info,
1776 +static int pcre2_test(const PCRE2Info *pcre2_info,
1790 - _ded.pcreOvectorInfo(&ovector, &ovector_size);
1792 - if(pcre_info == NULL
1793 + if(pcre2_info == NULL
1797 @@ -174,50 +209,59 @@ static int pcre_test(const PCREInfo *pcr
1801 + match_data = _ded.pcre2MatchDataCreate(_ded.pcre2OvectorSize(), NULL);
1802 + if (!match_data) {
1803 + DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
1804 + "Returning 0 because match data failed!\n"););
1810 - result = _ded.pcreExec(pcre_info->compiled_expr,/* result of pcre_compile() */
1811 - pcre_info->compiled_extra, /* result of pcre_study() */
1812 + result = _ded.pcre2MatchReal(pcre2_info->compiled_expr,/* result of pcre_compile() */
1813 buf, /* the subject string */
1814 len, /* the length of the subject string */
1815 start_offset, /* start at offset 0 in the subject */
1816 0, /* options(handled at compile time */
1817 - ovector, /* vector for substring information */
1818 - ovector_size); /* number of elements in the vector */
1819 + match_data, /* match_data vector */
1820 + pcre2_info->match_context); /* match context for limits */
1826 - else if(result == PCRE_ERROR_NOMATCH)
1827 + else if(result == PCRE2_ERROR_NOMATCH)
1833 - DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_exec error : %d \n", result););
1834 + _ded.pcre2MatchDataFree(match_data);
1835 + DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_match error : %d \n", result););
1841 + ovector = _ded.pcre2GetOvectorPointer(match_data);
1842 *found_offset = ovector[1];
1843 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
1844 "Setting buffer and found_offset: %p %d\n",
1845 buf, found_offset););
1848 + _ded.pcre2MatchDataFree(match_data);
1852 -ENGINE_LINKAGE int pcreMatch(void *p, PCREInfo* pcre_info, const uint8_t **cursor)
1853 +ENGINE_LINKAGE int pcre2Match(void *p, PCRE2Info* pcre_info, const uint8_t **cursor)
1855 if (pcre_info->flags & NOT_FLAG)
1856 return invertMatchResult(pcreMatchInternal(p, pcre_info, cursor));
1857 return pcreMatchInternal(p, pcre_info, cursor);
1860 -static int pcreMatchInternal(void *p, PCREInfo* pcre_info, const uint8_t **cursor)
1861 +static int pcreMatchInternal(void *p, PCRE2Info* pcre_info, const uint8_t **cursor)
1863 const uint8_t *buffer_start;
1865 @@ -295,7 +339,7 @@ static int pcreMatchInternal(void *p, PC
1869 - pcre_found = pcre_test(pcre_info, (const char *)buffer_start, buffer_len, pcre_info->offset, &pcre_offset);
1870 + pcre_found = pcre2_test(pcre_info, (const char *)buffer_start, buffer_len, pcre_info->offset, &pcre_offset);
1874 --- a/src/dynamic-preprocessors/appid/luaDetectorApi.c
1875 +++ b/src/dynamic-preprocessors/appid/luaDetectorApi.c
1877 #include "luaDetectorModule.h"
1878 #include "luaDetectorApi.h"
1879 #include "luaDetectorFlowApi.h"
1881 +#define PCRE2_CODE_UNIT_WIDTH 8
1883 #include "httpCommon.h"
1884 #include "sf_multi_mpse.h"
1885 #include "fw_appid.h"
1887 #include "detector_cip.h"
1889 #define DETECTOR "Detector"
1890 -#define OVECCOUNT 30 /* should be a multiple of 3 */
1891 #define URL_LIST_STEP_SIZE 5000
1894 @@ -1355,7 +1355,7 @@ static int Detector_getPacketDir(
1898 -/**Perform a pcre match with grouping. A simple regular expression match with no grouping
1899 +/**Perform a pcre2 match with grouping. A simple regular expression match with no grouping
1900 * can also be performed.
1902 * @param Lua_State* - Lua state variable.
1903 @@ -1371,12 +1371,15 @@ static int Detector_getPcreGroups(
1906 unsigned int offset;
1908 - int ovector[OVECCOUNT];
1909 - const char *error;
1912 + pcre2_match_data *match_data;
1913 + PCRE2_UCHAR error[128];
1915 + PCRE2_SIZE erroffset;
1917 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1918 + unsigned int oveccount;
1921 pattern = (char *)lua_tostring(L, 2);
1922 offset = lua_tonumber(L, 3); /*offset can be zero, no check necessary. */
1923 @@ -1390,49 +1393,56 @@ static int Detector_getPcreGroups(
1926 /*compile the regular expression pattern, and handle errors */
1927 - re = pcre_compile(
1928 - pattern, /*the pattern */
1929 - PCRE_DOTALL, /*default options - dot matches everything including newline */
1930 - &error, /*for error message */
1931 - &erroffset, /*for error offset */
1932 - NULL); /*use default character tables */
1933 + re = pcre2_compile(
1934 + (PCRE2_SPTR)pattern, /*the pattern */
1935 + PCRE2_ZERO_TERMINATED, /*zero terminated string*/
1936 + PCRE2_DOTALL, /*default options - dot matches everything including newline */
1937 + &errorcode, /*for error message */
1938 + &erroffset, /*for error offset */
1939 + NULL); /*use default character tables */
1943 - _dpd.errMsg("PCRE compilation failed at offset %d: %s\n",erroffset, error);
1944 + pcre2_get_error_message(errorcode, error, 128);
1945 + _dpd.errMsg("PCRE2 compilation failed at offset %zu: %s\n",erroffset, error);
1949 + match_data = pcre2_match_data_create_from_pattern(re, NULL);
1950 + if (!match_data) {
1951 + _dpd.errMsg("PCRE2 failed to alloc data for match data\n");
1955 /*pattern match against the subject string. */
1958 re, /*compiled pattern */
1959 - NULL, /*no extra data */
1960 - (char *)detector->validateParams.data, /*subject string */
1961 - detector->validateParams.size, /*length of the subject */
1962 - offset, /*offset 0 */
1963 + (PCRE2_SPTR)detector->validateParams.data, /*subject string */
1964 + (PCRE2_SIZE)detector->validateParams.size, /*length of the subject */
1965 + (PCRE2_SIZE)offset, /*offset 0 */
1966 0, /*default options */
1967 - ovector, /*output vector for substring information */
1968 - OVECCOUNT); /*number of elements in the output vector */
1970 + match_data, /*output vector for substring information */
1971 + NULL); /*number of elements in the output vector */
1975 /*Matching failed: clubbing PCRE_ERROR_NOMATCH with other errors. */
1977 + pcre2_match_data_free(match_data);
1978 + pcre2_code_free(re);
1984 /*printf("\nMatch succeeded at offset %d", ovector[0]); */
1987 + oveccount = pcre2_get_ovector_count(match_data);
1988 + ovector = pcre2_get_ovector_pointer(match_data);
1992 /*overflow of matches */
1995 /*printf("ovector only has room for %d captured substrings", rc - 1); */
1996 _dpd.errMsg("ovector only has room for %d captured substrings\n",rc - 1);
1998 @@ -1447,6 +1457,9 @@ static int Detector_getPcreGroups(
1999 lua_pushlstring(L, (char *)detector->validateParams.data + ovector[2*i], ovector[2*i+1] - ovector[2*i]);
2002 + pcre2_match_data_free(match_data);
2003 + pcre2_code_free(re);
2008 --- a/src/dynamic-preprocessors/imap/snort_imap.h
2009 +++ b/src/dynamic-preprocessors/imap/snort_imap.h
2012 /* Includes ***************************************************************/
2015 +#define PCRE2_CODE_UNIT_WIDTH 8
2018 #include "sf_snort_packet.h"
2019 #include "imap_config.h"
2020 @@ -216,8 +217,7 @@ typedef struct _IMAPMimeBoundary
2022 typedef struct _IMAPPcre
2030 --- a/src/dynamic-preprocessors/pop/snort_pop.h
2031 +++ b/src/dynamic-preprocessors/pop/snort_pop.h
2034 /* Includes ***************************************************************/
2037 +#define PCRE2_CODE_UNIT_WIDTH 8
2040 #include "sf_snort_packet.h"
2041 #include "pop_config.h"
2042 --- a/src/dynamic-preprocessors/smtp/snort_smtp.h
2043 +++ b/src/dynamic-preprocessors/smtp/snort_smtp.h
2046 /* Includes ***************************************************************/
2049 +#define PCRE2_CODE_UNIT_WIDTH 8
2052 #include "sf_snort_packet.h"
2056 @@ -4449,9 +4449,6 @@ void SnortConfFree(SnortConfig *sc)
2058 OtnxMatchDataFree(sc->omd);
2060 - if (sc->pcre_ovector != NULL)
2061 - free(sc->pcre_ovector);
2063 if ( sc->event_queue_config )
2064 EventQueueConfigFree(sc->event_queue_config);
2068 @@ -826,7 +826,6 @@ typedef struct _SnortConfig
2069 long int tagged_packet_limit; /* config tagged_packet_limit */
2070 long int pcre_match_limit; /* config pcre_match_limit */
2071 long int pcre_match_limit_recursion; /* config pcre_match_limit_recursion */
2072 - int *pcre_ovector;
2073 int pcre_ovector_size;
2075 #ifdef PERF_PROFILING
2078 @@ -78,7 +78,8 @@ static struct mallinfo mi;
2079 #include "plugbase.h"
2080 #include "sf_types.h"
2083 +#define PCRE2_CODE_UNIT_WIDTH 8
2088 @@ -175,7 +176,7 @@ double CalcPct(uint64_t cnt, uint64_t to
2089 int DisplayBanner(void)
2092 - const char * pcre_ver;
2093 + PCRE2_UCHAR buffer[32];
2094 const char * zlib_ver;
2096 info = getenv("HOSTTYPE");
2097 @@ -184,7 +185,7 @@ int DisplayBanner(void)
2101 - pcre_ver = pcre_version();
2102 + pcre2_config(PCRE2_CONFIG_VERSION, buffer);
2103 zlib_ver = zlib_version;
2106 @@ -204,7 +205,7 @@ int DisplayBanner(void)
2107 #ifdef HAVE_PCAP_LIB_VERSION
2108 LogMessage(" Using %s\n", pcap_lib_version());
2110 - LogMessage(" Using PCRE version: %s\n", pcre_ver);
2111 + LogMessage(" Using PCRE2 version: %s\n", buffer);
2112 LogMessage(" Using ZLIB version: %s\n", zlib_ver);