4e01347af3236fd12f4113f0ec4aea67dd8be31e
[feed/packages.git] / net / snort / patches / 900-Convert-project-to-PCRE2.patch
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
5
6 Convert project to PCRE2. Convert every example to PCRE2.
7
8 Due to API changes examples needs to be updated accordingly with the new
9 struct and API.
10
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.
13
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
16 library).
17
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
20 additional info.
21
22 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
23 ---
24 config.h.in | 8 +-
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 +-
51 src/snort.c | 3 -
52 src/snort.h | 1 -
53 src/util.c | 9 +-
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
57
58 --- a/config.h.in
59 +++ b/config.h.in
60 @@ -133,8 +133,8 @@
61 /* Define to 1 if you have the `pcap' library (-lpcap). */
62 #undef HAVE_LIBPCAP
63
64 -/* Define to 1 if you have the `pcre' library (-lpcre). */
65 -#undef HAVE_LIBPCRE
66 +/* Define to 1 if you have the `pcre2' library (-lpcre2-8). */
67 +#undef HAVE_LIBPCRE2
68
69 /* Define to 1 if you have the `pfring' library (-lpfring). */
70 #undef HAVE_LIBPFRING
71 @@ -190,8 +190,8 @@
72 /* Can output the library version. */
73 #undef HAVE_PCAP_LIB_VERSION
74
75 -/* Define to 1 if you have the <pcre.h> header file. */
76 -#undef HAVE_PCRE_H
77 +/* Define to 1 if you have the <pcre2.h> header file. */
78 +#undef HAVE_PCRE2_H
79
80 /* Define to 1 if you have the <pfring.h> header file. */
81 #undef HAVE_PFRING_H
82 --- a/configure.in
83 +++ b/configure.in
84 @@ -455,65 +455,70 @@ AC_DEFUN([FAIL_MESSAGE],[
85 exit 1
86 ])
87
88 -AC_ARG_WITH(libpcre_includes,
89 - [ --with-libpcre-includes=DIR libpcre include directory],
90 - [with_libpcre_includes="$withval"],[with_libpcre_includes="no"])
91 -
92 -AC_ARG_WITH(libpcre_libraries,
93 - [ --with-libpcre-libraries=DIR libpcre library directory],
94 - [with_libpcre_libraries="$withval"],[with_libpcre_libraries="no"])
95 -
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"])
102 +
103 +AC_ARG_WITH(libpcre2_libraries,
104 + [ --with-libpcre2-libraries=DIR libpcre2 library directory],
105 + [with_libpcre2_libraries="$withval"],[with_libpcre2_libraries="no"])
106 +
107 +if test "x$with_libpcre2_includes" != "xno"; then
108 + CPPFLAGS="${CPPFLAGS} -I${with_libpcre2_includes}"
109 + ICONFIGFLAGS="${ICONFIGFLAGS} -I${with_libpcre2_includes}"
110 else
111 - CPPFLAGS="${CPPFLAGS} `pcre-config --cflags`"
112 + CPPFLAGS="${CPPFLAGS} `pcre2-config --cflags`"
113 fi
114
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}"
119 else
120 - LDFLAGS="${LDFLAGS} `pcre-config --libs`"
121 + LDFLAGS="${LDFLAGS} `pcre2-config --libs8`"
122 fi
123
124 -# PCRE configuration (required)
125 +# PCRE2 configuration (required)
126 # Verify that we have the headers
127 -PCRE_H=""
128 -AC_CHECK_HEADERS(pcre.h,, PCRE_H="no")
129 -if test "x$PCRE_H" = "xno"; then
130 +PCRE2_H=""
131 +AC_CHECK_HEADERS(pcre2.h,, PCRE2_H="no",[#define PCRE2_CODE_UNIT_WIDTH 8])
132 +if test "x$PCRE2_H" = "xno"; then
133 echo
134 - echo " ERROR! Libpcre header not found."
135 + echo " ERROR! Libpcre2 header not found."
136 echo " Get it from http://www.pcre.org"
137 exit 1
138 fi
139
140 # Verify that we have the library
141 -PCRE_L=""
142 -pcre_version_six=""
143 -AC_CHECK_LIB(pcre, pcre_compile, ,PCRE_L="no")
144 +PCRE2_L=""
145 +pcre2_version_six=""
146 +AC_CHECK_LIB(pcre2-8, pcre2_compile_8, ,PCRE2_L="no")
147 if test "x$PCRE_L" = "xno"; then
148 echo
149 - echo " ERROR! Libpcre library not found."
150 + echo " ERROR! Libpcre2 library not found."
151 echo " Get it from http://www.pcre.org"
152 echo
153 exit 1
154 else
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
161 + #include <pcre2.h>
162 + ]], [[
163 + #if (PCRE2_MAJOR < 10)
164 #error "Version failure"
165 #else
166 - int a, b = 0, c = 0, d = 0;
167 - pcre *tmp = NULL;
168 - a = pcre_copy_named_substring(tmp, "", &b, c, "", "", d);
169 + int a;
170 + PCRE2_UCHAR b = { 0 };
171 + PCRE2_SIZE c;
172 + pcre2_match_data *match_data = NULL;
173 + a = pcre2_substring_copy_byname(match_data, (PCRE2_SPTR )"", &b, &c);
174 #endif
175 - ]])],[pcre_version_six="yes"],[pcre_version_six="no"])
176 + ]])],[pcre2_version_ten="yes"],[pcre2_version_ten="no"])
177 fi
178
179 -if test "x$pcre_version_six" != "xyes"; then
180 +if test "x$pcre2_version_ten" != "xyes"; then
181 AC_MSG_RESULT(no)
182 echo
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"
186 echo
187 exit 1
188 --- a/src/detection-plugins/sp_pcre.c
189 +++ b/src/detection-plugins/sp_pcre.c
190 @@ -46,7 +46,8 @@
191
192 #include "sp_pcre.h"
193
194 -#include <pcre.h>
195 +#define PCRE2_CODE_UNIT_WIDTH 8
196 +#include <pcre2.h>
197
198 #include "snort.h"
199 #include "profiler.h"
200 @@ -60,7 +61,7 @@ extern PreprocStats ruleOTNEvalPerfStats
201 #include "detection_util.h"
202
203 /*
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;
211
212 free(data->expression);
213 - free(data->re);
214 - free(data->pe);
215 + pcre2_match_context_free(data->match_context);
216 + pcre2_code_free(data->re);
217 free(data);
218 }
219
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;
226 }
227
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;
231
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
238
239 if (sc->pcre_ovector_size > s_ovector_max)
240 s_ovector_max = sc->pcre_ovector_size;
241 -
242 - sc->pcre_ovector = (int *) SnortAlloc(s_ovector_max*sizeof(int));
243 }
244
245 #if SNORT_RELOAD
246 @@ -218,12 +216,12 @@ static void Ovector_Reload(struct _Snort
247 }
248 #endif
249
250 -void PcreCapture(struct _SnortConfig *sc, const void *code, const void *extra)
251 +void Pcre2Capture(struct _SnortConfig *sc, const void *code)
252 {
253 int tmp_ovector_size = 0;
254
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);
259
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 *
263
264 if (pcre_data->expression)
265 free(pcre_data->expression);
266 - if (pcre_data->pe)
267 - free(pcre_data->pe);
268 + if (pcre_data->match_context)
269 + pcre2_match_context_free(pcre_data->match_context);
270 if (pcre_data->re)
271 - free(pcre_data->re);
272 + pcre2_code_free(pcre_data->re);
273
274 free(pcre_data);
275 pcre_data = pcre_dup;
276 @@ -305,11 +303,12 @@ static inline void ValidatePcreHttpConte
277
278 void SnortPcreParse(struct _SnortConfig *sc, char *data, PcreData *pcre_data, OptTreeNode *otn)
279 {
280 - const char *error;
281 + PCRE2_UCHAR error[128];
282 char *re, *free_me;
283 char *opts;
284 char delimit = '/';
285 - int erroffset;
286 + int errorcode;
287 + PCRE2_SIZE erroffset;
288 int compile_flags = 0;
289 unsigned http = 0;
290
291 @@ -381,17 +380,17 @@ void SnortPcreParse(struct _SnortConfig
292 /* process any /regex/ismxR options */
293 while(*opts != '\0') {
294 switch(*opts) {
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;
303
304 /*
305 * these are pcre specific... don't work with perl
306 */
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;
313
314 /*
315 * these are snort specific don't work with pcre or perl
316 @@ -424,45 +423,37 @@ void SnortPcreParse(struct _SnortConfig
317
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);
322
323 if(pcre_data->re == NULL)
324 {
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);
329 }
330
331 + /* now create match context */
332 + pcre_data->match_context = pcre2_match_context_create(NULL);
333 + if(pcre_data->match_context == NULL)
334 + {
335 + FatalError("%s(%d) : failed to allocate memory for match context\n",
336 + file_name, file_line);
337 + }
338
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);
342
343 - if (pcre_data->pe)
344 + if (!errorcode)
345 {
346 if ((ScPcreMatchLimitNewConf(sc) != -1) && !(pcre_data->options & SNORT_OVERRIDE_MATCH_LIMIT))
347 {
348 - if (pcre_data->pe->flags & PCRE_EXTRA_MATCH_LIMIT)
349 - {
350 - pcre_data->pe->match_limit = ScPcreMatchLimitNewConf(sc);
351 - }
352 - else
353 - {
354 - pcre_data->pe->flags |= PCRE_EXTRA_MATCH_LIMIT;
355 - pcre_data->pe->match_limit = ScPcreMatchLimitNewConf(sc);
356 - }
357 + pcre2_set_match_limit(pcre_data->match_context, ScPcreMatchLimitNewConf(sc));
358 }
359
360 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
361 if ((ScPcreMatchLimitRecursionNewConf(sc) != -1) && !(pcre_data->options & SNORT_OVERRIDE_MATCH_LIMIT))
362 {
363 - if (pcre_data->pe->flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION)
364 - {
365 - pcre_data->pe->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
366 - }
367 - else
368 - {
369 - pcre_data->pe->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
370 - pcre_data->pe->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
371 - }
372 + pcre2_set_depth_limit(pcre_data->match_context, ScPcreMatchLimitRecursionNewConf(sc));
373 }
374 #endif
375 }
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)))
379 {
380 - pcre_data->pe = (pcre_extra *)SnortAlloc(sizeof(pcre_extra));
381 if (ScPcreMatchLimitNewConf(sc) != -1)
382 {
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));
386 }
387
388 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
389 if (ScPcreMatchLimitRecursionNewConf(sc) != -1)
390 {
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));
394 }
395 #endif
396 }
397 }
398
399 - if(error != NULL)
400 + if(errorcode)
401 {
402 + pcre2_get_error_message(errorcode, error, 128);
403 FatalError("%s(%d) : pcre study failed : %s\n", file_name,
404 file_line, error);
405 }
406
407 - PcreCapture(sc, pcre_data->re, pcre_data->pe);
408 + Pcre2Capture(sc, pcre_data->re);
409
410 PcreCheckAnchored(pcre_data);
411
412 @@ -515,13 +504,13 @@ void PcreCheckAnchored(PcreData *pcre_da
413 int rc;
414 unsigned long int options = 0;
415
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))
418 return;
419
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);
422 switch (rc)
423 {
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 */
431 break;
432
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",
437 __FILE__, __LINE__);
438
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__);
444
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",
449 __FILE__, __LINE__);
450
451 default:
452 - FatalError("%s(%d) pcre_fullinfo: Unknown error code.\n",
453 + FatalError("%s(%d) pcre2_pattern_info: Unknown error code.\n",
454 __FILE__, __LINE__);
455 }
456
457 - if ((options & PCRE_ANCHORED) && !(options & PCRE_MULTILINE))
458 + if ((options & PCRE2_ANCHORED) && !(options & PCRE2_MULTILINE))
459 {
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
463 int start_offset,
464 int *found_offset)
465 {
466 + pcre2_match_data *match_data;
467 + PCRE2_SIZE *ovector;
468 int matched;
469 int result;
470
471 @@ -596,14 +587,19 @@ static int pcre_search(const PcreData *p
472
473 *found_offset = -1;
474
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);
484 + if (!match_data) {
485 + DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre2_match_data_create failed to alloc mem!\n"););
486 + return 0;
487 + }
488 +
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 */
496
497 if(result >= 0)
498 {
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.
506 *
507 * In Snort's case, the ovector size only allows for the first pair and a single int for scratch space.
508 */
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););
515 }
516 - else if(result == PCRE_ERROR_NOMATCH)
517 + else if(result == PCRE2_ERROR_NOMATCH)
518 {
519 matched = 0;
520 }
521 else
522 {
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););
526 return 0;
527 }
528
529 @@ -641,6 +639,7 @@ static int pcre_search(const PcreData *p
530 matched = !matched;
531 }
532
533 + pcre2_match_data_free(match_data);
534 return matched;
535 }
536
537 --- a/src/detection-plugins/sp_pcre.h
538 +++ b/src/detection-plugins/sp_pcre.h
539 @@ -49,17 +49,18 @@
540
541 void SetupPcre(void);
542
543 -#include <pcre.h>
544 +#define PCRE2_CODE_UNIT_WIDTH 8
545 +#include <pcre2.h>
546 typedef struct _PcreData
547 {
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) */
553 char *expression;
554 uint32_t search_offset;
555 } PcreData;
556
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
564 @@ -52,9 +52,11 @@
565
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);
576
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)
581 {
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;
585 OptFpList *fpl;
586 void *pcre_dup;
587 - const char *error;
588 - int erroroffset;
589 + int errorcode;
590 + size_t erroroffset;
591
592 /* Need to recompile the expression so double free doesn't occur
593 * during reload */
594
595 /* Compile & Study PCRE */
596 - pcre_data->re = pcreCompile(
597 - pcre_info->expr,
598 - pcre_info->compile_flags,
599 - &error,
600 + pcre_data->re = pcre2Compile(
601 + pcre2_info->expr,
602 + pcre2_info->compile_flags,
603 + &errorcode,
604 &erroroffset,
605 NULL
606 );
607 @@ -541,37 +543,46 @@ static int ConvertPcreOption(SnortConfig
608 return -1;
609 }
610
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);
615 + free(pcre_data);
616 + return -1;
617 + }
618 +
619 + errorcode = pcre2JITCompile(
620 + sc,
621 pcre_data->re,
622 - pcre_info->compile_flags,
623 - &error
624 + pcre_data->match_context,
625 + pcre2_info->compile_flags
626 );
627
628 - if (error)
629 + if (errorcode)
630 {
631 - free(pcre_data->re);
632 + pcre2MatchContextFree(pcre_data->match_context);
633 + pcre2CodeFree(pcre_data->re);
634 free(pcre_data);
635 return -1;
636 }
637
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);
641
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;
647
648 - if (pcre_info->flags & NOT_FLAG)
649 + if (pcre2_info->flags & NOT_FLAG)
650 pcre_data->options |= SNORT_PCRE_INVERT;
651
652 - if (pcre_info->flags & CONTENT_BUF_RAW)
653 + if (pcre2_info->flags & CONTENT_BUF_RAW)
654 pcre_data->options |= SNORT_PCRE_RAWBYTES;
655
656 - if (pcre_info->flags & CONTENT_BUF_NORMALIZED)
657 + if (pcre2_info->flags & CONTENT_BUF_NORMALIZED)
658 pcre_data->options &= ~SNORT_PCRE_RAWBYTES;
659
660 - pcre_data->options |= HTTP_CONTENT(pcre_info->flags);
661 + pcre_data->options |= HTTP_CONTENT(pcre2_info->flags);
662
663 PcreCheckAnchored(pcre_data);
664
665 @@ -584,10 +595,10 @@ static int ConvertPcreOption(SnortConfig
666 {
667 if (pcre_data->expression)
668 free(pcre_data->expression);
669 - if (pcre_data->pe)
670 - free(pcre_data->pe);
671 + if (pcre_data->match_context)
672 + pcre2MatchContextFree(pcre_data->match_context);
673 if (pcre_data->re)
674 - free(pcre_data->re);
675 + pcre2CodeFree(pcre_data->re);
676
677 free(pcre_data);
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
682
683 #define ENGINE_DATA_VERSION 10
684
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 *);
702
703 typedef struct _DynamicEngineData
704 {
705 @@ -175,9 +182,15 @@ typedef struct _DynamicEngineData
706 char **debugMsgFile;
707 int *debugMsgLine;
708
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;
721 SfUnfold sfUnfold;
722 SfBase64Decode sfbase64decode;
723 GetAltDetectFunc GetAltDetect;
724 @@ -190,8 +203,7 @@ typedef struct _DynamicEngineData
725
726 UnregisterBit flowbitUnregister;
727
728 - PCRECapture pcreCapture;
729 - PCREOvectorInfo pcreOvectorInfo;
730 + PCRE2Capture pcre2Capture;
731
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;
737 #include "sf_iph.h"
738 #include "fpdetect.h"
739 #include "sfportobject.h"
740 -#include <pcre.h>
741 +#define PCRE2_CODE_UNIT_WIDTH 8
742 +#include <pcre2.h>
743 #include "parser.h"
744 #include "event_wrapper.h"
745 #include "util.h"
746 @@ -1250,46 +1251,35 @@ void DynamicGetRuleData(void *p, const R
747 }
748 }
749
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)
752 {
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);
756 }
757
758 -void *pcreStudy(struct _SnortConfig *sc, const void *code, int options, const char **errptr)
759 +void *pcre2MatchContextCreate(const void *generalcontext)
760 +{
761 + return (void *)pcre2_match_context_create((pcre2_general_context *)generalcontext);
762 +}
763 +
764 +int pcre2JITCompile(struct _SnortConfig *sc, const void *code, const void *matchcontext, int options)
765 {
766 - pcre_extra *extra_extra;
767 int snort_options = options & SNORT_PCRE_OVERRIDE_MATCH_LIMIT;
768 + int errorcode;
769
770 - extra_extra = pcre_study((const pcre*)code, 0, errptr);
771 + errorcode = pcre2_jit_compile((pcre2_code*)code, PCRE2_JIT_COMPLETE);
772
773 - if (extra_extra)
774 + if (errorcode)
775 {
776 if ((ScPcreMatchLimitNewConf(sc) != -1) && !(snort_options & SNORT_PCRE_OVERRIDE_MATCH_LIMIT))
777 {
778 - if (extra_extra->flags & PCRE_EXTRA_MATCH_LIMIT)
779 - {
780 - extra_extra->match_limit = ScPcreMatchLimitNewConf(sc);
781 - }
782 - else
783 - {
784 - extra_extra->flags |= PCRE_EXTRA_MATCH_LIMIT;
785 - extra_extra->match_limit = ScPcreMatchLimitNewConf(sc);
786 - }
787 + pcre2_set_match_limit((pcre2_match_context*)matchcontext, ScPcreMatchLimitNewConf(sc));
788 }
789
790 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
791 if ((ScPcreMatchLimitRecursionNewConf(sc) != -1) && !(snort_options & SNORT_PCRE_OVERRIDE_MATCH_LIMIT))
792 {
793 - if (extra_extra->flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION)
794 - {
795 - extra_extra->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
796 - }
797 - else
798 - {
799 - extra_extra->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
800 - extra_extra->match_limit_recursion = ScPcreMatchLimitRecursionNewConf(sc);
801 - }
802 + pcre2_set_depth_limit((pcre2_match_context*)matchcontext, ScPcreMatchLimitRecursionNewConf(sc));
803 }
804 #endif
805 }
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)))
809 {
810 - extra_extra = (pcre_extra *)SnortAlloc(sizeof(pcre_extra));
811 if (ScPcreMatchLimitNewConf(sc) != -1)
812 {
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));
816 }
817
818 #ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
819 if (ScPcreMatchLimitRecursionNewConf(sc) != -1)
820 {
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));
824 }
825 #endif
826 }
827 }
828
829 - return extra_extra;
830 + return errorcode;
831 +}
832 +
833 +int pcre2OvectorSize(void)
834 +{
835 + return snort_conf->pcre_ovector_size;
836 +}
837 +
838 +void *pcre2MatchDataCreate(int size, const void *generalcontext)
839 +{
840 + return pcre2_match_data_create(size, (pcre2_general_context *)generalcontext);
841 +}
842 +
843 +unsigned int pcre2GetOvectorCount(const void *match_data)
844 +{
845 + return pcre2_get_ovector_count((pcre2_match_data *)match_data);
846 +}
847 +
848 +void *pcre2GetOvectorPointer(const void *match_data)
849 +{
850 + return pcre2_get_ovector_pointer((pcre2_match_data *)match_data);
851 +}
852 +
853 +int pcre2MatchReal(const void *code, const char *subj,
854 + int len, int start, int options, const void *matchdata, const void *matchcontext)
855 +{
856 + return pcre2_match((const pcre2_code *)code, (PCRE2_SPTR)subj, len, start, options, (pcre2_match_data *)matchdata, (pcre2_match_context *)matchcontext);
857 +}
858 +
859 +void pcre2MatchDataFree(const void *match_data)
860 +{
861 + pcre2_match_data_free((pcre2_match_data *)match_data);
862 }
863
864 -/* pcreOvectorInfo
865 - *
866 - * Get the Ovector configuration for PCRE from the snort.conf
867 - */
868 -void pcreOvectorInfo(int **ovector, int *ovector_size)
869 +void pcre2MatchContextFree(const void *code)
870 {
871 - *ovector = snort_conf->pcre_ovector;
872 - *ovector_size = snort_conf->pcre_ovector_size;
873 + pcre2_match_context_free((pcre2_match_context *)code);
874 }
875
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)
879 {
880 - return pcre_exec((const pcre *)code, (const pcre_extra *)extra, subj, len, start, options, ovec, ovecsize);
881 + pcre2_code_free((pcre2_code *)code);
882 }
883
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;
887 #endif
888
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;
901
902 engineData.allocRuleData = &DynamicRuleDataAlloc;
903 engineData.freeRuleData = &DynamicRuleDataFree;
904
905 engineData.flowbitUnregister = &DynamicFlowbitUnregister;
906
907 - engineData.pcreCapture = &PcreCapture;
908 - engineData.pcreOvectorInfo = &pcreOvectorInfo;
909 + engineData.pcre2Capture = &Pcre2Capture;
910 engineData.getHttpBuffer = getHttpBuffer;
911
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 }
917 };
918 // pcre:"^.{27}", relative;
919 -static PCREInfo rule3036pcre4 =
920 +static PCRE2Info rule3036pcre4 =
921 {
922 "^.{27}", /* pattern */
923 NULL, /* holder for compiled pattern */
924 @@ -166,7 +166,7 @@ static RuleOption rule3036option6 =
925 { &rule3036byte_jump6 }
926 };
927 // pcre:"^.{4}", relative;
928 -static PCREInfo rule3036pcre7 =
929 +static PCRE2Info rule3036pcre7 =
930 {
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 }
953 };
954 // pcre:"^.{27}", relative;
955 -static PCREInfo rule3052pcre3 =
956 +static PCRE2Info rule3052pcre3 =
957 {
958 "^.{27}", /* pattern */
959 NULL, /* holder for compiled pattern */
960 @@ -155,7 +155,7 @@ static RuleOption rule3052option5 =
961 { &rule3052byte_jump5 }
962 };
963 // pcre:"^.{4}", relative;
964 -static PCREInfo rule3052pcre6 =
965 +static PCRE2Info rule3052pcre6 =
966 {
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 }
989 };
990 // pcre:"^.{27}", relative;
991 -static PCREInfo rule3099pcre4 =
992 +static PCRE2Info rule3099pcre4 =
993 {
994 "^.{27}", /* pattern */
995 NULL, /* holder for compiled pattern */
996 @@ -191,7 +191,7 @@ static RuleOption rule3099option7 =
997 { &rule3099byte_jump7 }
998 };
999 // pcre:"^.{4}", relative;
1000 -static PCREInfo rule3099pcre8 =
1001 +static PCRE2Info rule3099pcre8 =
1002 {
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
1025 @@ -25,7 +25,8 @@
1026 #include "config.h"
1027 #endif
1028
1029 -#include "pcre.h"
1030 +#define PCRE2_CODE_UNIT_WIDTH 8
1031 +#include <pcre2.h>
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
1036 };
1037
1038 // pcre:"/^Authorization:\s*Basic/mi";
1039 -static PCREInfo ruleAPACHEAUTHLDAPpcre0 =
1040 +static PCRE2Info ruleAPACHEAUTHLDAPpcre0 =
1041 {
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
1048 0 /* offset */
1049 };
1050 @@ -99,7 +100,7 @@ static RuleOption ruleAPACHEAUTHLDAPopti
1051 };
1052
1053 // pcre:"/%[0-9]*\.?[0-9]*[:formatspecifiers:]/";
1054 -static PCREInfo ruleAPACHEAUTHLDAPpcre1 =
1055 +static PCRE2Info ruleAPACHEAUTHLDAPpcre1 =
1056 {
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 *
1060
1061 // manual pcre stuff
1062 int result;
1063 - int ovector[3]; // Needs to be a multiple of 3
1064 + void *match_data;
1065
1066 if(sp == NULL)
1067 return RULE_NOMATCH;
1068 @@ -221,7 +222,7 @@ static int ruleAPACHEAUTHLDAPeval(void *
1069 //DEBUG_WRAP(printf("found content:\"Authorization:\" %p\n", cursor));
1070
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;
1075
1076 //DEBUG_WRAP(printf("found pcre:\"/^Authorization:\\s*Basic\\s+/mi\" %p\n", cursor));
1077 @@ -238,14 +239,35 @@ static int ruleAPACHEAUTHLDAPeval(void *
1078
1079 //DEBUG_WRAP(printf("Successfully base64 decoded (%s)(%d)\n", decodedbuf, decodedbytes));
1080
1081 + match_data = pcre2MatchDataCreateWrapper();
1082 + if (!match_data)
1083 + return RULE_NOMATCH;
1084 +
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
1090 0, // start offset
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
1095 +
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
1101 + *
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
1107 + *
1108 + * ALWAYS REMEMBER TO USE THE MATCH DATA CREATE AND FREE BEFORE
1109 + * EXEC WRAPPER
1110 + */
1111 +
1112 + pcre2MatchDataFreeWrapper(match_data);
1113
1114 //DEBUG_WRAP(printf("result = %d\n", result));
1115
1116 --- a/src/dynamic-plugins/sf_engine/examples/3682.c
1117 +++ b/src/dynamic-plugins/sf_engine/examples/3682.c
1118 @@ -9,7 +9,8 @@
1119 #include "config.h"
1120 #endif
1121
1122 -#include "pcre.h"
1123 +#define PCRE2_CODE_UNIT_WIDTH 8
1124 +#include <pcre2.h>
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 =
1129
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 =
1134 {
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 */
1141 0 /* offset */
1142 };
1143 @@ -148,12 +149,12 @@ static RuleOption rule3682option5 =
1144
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 =
1149 {
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 */
1156 0 /* offset */
1157 };
1158 --- a/src/dynamic-plugins/sf_engine/examples/bug31842.c
1159 +++ b/src/dynamic-plugins/sf_engine/examples/bug31842.c
1160 @@ -25,7 +25,8 @@
1161 #include "config.h"
1162 #endif
1163
1164 -#include "pcre.h"
1165 +#define PCRE2_CODE_UNIT_WIDTH 8
1166 +#include <pcre2.h>
1167 #include "sf_snort_plugin_api.h"
1168 #include "sf_snort_packet.h"
1169
1170 @@ -89,12 +90,12 @@ static RuleOption ruleSQUID_NTLM_AUTHopt
1171 }
1172 };
1173
1174 -static PCREInfo ruleSQUID_NTLM_AUTHpcre =
1175 +static PCRE2Info ruleSQUID_NTLM_AUTHpcre =
1176 {
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 */
1183 0 /* offset */
1184 };
1185 @@ -336,7 +337,7 @@ int ruleSQUID_NTLM_AUTHeval(void *p) {
1186 }
1187
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;
1192 }
1193
1194 --- a/src/dynamic-plugins/sf_engine/examples/bug35218.c
1195 +++ b/src/dynamic-plugins/sf_engine/examples/bug35218.c
1196 @@ -26,7 +26,8 @@
1197 #include "config.h"
1198 #endif
1199
1200 -#include "pcre.h"
1201 +#define PCRE2_CODE_UNIT_WIDTH 8
1202 +#include <pcre2.h>
1203 #include "sf_snort_plugin_api.h"
1204 #include "sf_snort_packet.h"
1205
1206 @@ -97,12 +98,12 @@ static RuleOption ruleEXCHANGE_BASE64_DE
1207 }
1208 };
1209
1210 -static PCREInfo ruleEXCHANGE_BASE64_DECODEpcre0 =
1211 +static PCRE2Info ruleEXCHANGE_BASE64_DECODEpcre0 =
1212 {
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 */
1219 0 /* offset */
1220 };
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.
1224 */
1225 -static PCREInfo ruleEXCHANGE_BASE64_DECODEpcre1 =
1226 +static PCRE2Info ruleEXCHANGE_BASE64_DECODEpcre1 =
1227 {
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 */
1234 0 /* offset */
1235 };
1236 @@ -214,7 +215,7 @@ int ruleEXCHANGE_BASE64_DECODEeval(void
1237 }
1238
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;
1243 }
1244
1245 @@ -286,7 +287,7 @@ int ruleEXCHANGE_BASE64_DECODEeval(void
1246
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;
1252
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
1256 @@ -12,7 +12,8 @@
1257 #include "config.h"
1258 #endif
1259
1260 -#include "pcre.h"
1261 +#define PCRE2_CODE_UNIT_WIDTH 8
1262 +#include <pcre2.h>
1263 #include "sf_snort_plugin_api.h"
1264 #include "sf_snort_packet.h"
1265
1266 @@ -59,12 +60,12 @@ static RuleOption rule1902option1 =
1267 { &rule1902content1 }
1268 };
1269 // pcre:"\sLSUB\s[^\n]*?\s\{", dotall, multiline, nocase;
1270 -static PCREInfo rule1902pcre2 =
1271 +static PCRE2Info rule1902pcre2 =
1272 {
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 */
1279 0 /* offset */
1280 };
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) {
1289 return RULE_MATCH;
1290 --- a/src/dynamic-plugins/sf_engine/examples/sid2389.c
1291 +++ b/src/dynamic-plugins/sf_engine/examples/sid2389.c
1292 @@ -6,7 +6,8 @@
1293 #include "config.h"
1294 #endif
1295
1296 -#include "pcre.h"
1297 +#define PCRE2_CODE_UNIT_WIDTH 8
1298 +#include <pcre2.h>
1299 #include "sf_snort_plugin_api.h"
1300 #include "detection_lib_meta.h"
1301
1302 @@ -113,12 +114,12 @@ static RuleOption option2 =
1303 { &content1 }
1304 };
1305
1306 -static PCREInfo pcre1 =
1307 +static PCRE2Info pcre1 =
1308 { /* PCRE */
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 */
1315 0 /* offset */
1316 };
1317 @@ -178,7 +179,7 @@ int sid2389Eval(void *p)
1318 if (contentMatch(p, sid2389.options[1]->option_u.content, &norm_cur)>0)
1319 {
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))
1323 {
1324 return RULE_MATCH;
1325 }
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 =
1334 {
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 =
1340 };
1341
1342 // pcre:"IIS 7\x2e5 Detailed Error - 404\x2e0 - Not Found", nocase;
1343 -static PCREInfo rule64111pcre2 =
1344 +static PCRE2Info rule64111pcre2 =
1345 {
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 */
1352 0 /* offset */
1353 };
1354 @@ -256,12 +256,12 @@ static RuleOption rule64222option2 =
1355 };
1356
1357 // pcre:"SignUrl=[^\x26\s]*[\x22\x27\x28\x29\x3C\x3E]", payload uri, nocase;
1358 -static PCREInfo rule64222pcre3 =
1359 +static PCRE2Info rule64222pcre3 =
1360 {
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 */
1367 0 /* offset */
1368 };
1369 @@ -428,12 +428,12 @@ static RuleOption rule64333option2 =
1370 };
1371
1372 // pcre:"SignUrl=[^\\x26\\s]*[\\x22\\x27\\x28\\x29\\x3C\\x3E]", payload uri, nocase;
1373 -static PCREInfo rule64333pcre3 =
1374 +static PCRE2Info rule64333pcre3 =
1375 {
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 */
1382 0 /* offset */
1383 };
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)) {
1390 return RULE_MATCH;
1391 }
1392 }
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)) {
1399 return RULE_MATCH;
1400 }
1401 }
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)) {
1408 return RULE_MATCH;
1409 }
1410 }
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
1414 break;
1415 case OPTION_TYPE_PCRE:
1416 {
1417 - PCREInfo *pcre = option->option_u.pcre;
1418 + PCRE2Info *pcre2 = option->option_u.pcre2;
1419
1420 - if (pcre->compiled_expr == NULL)
1421 + if (pcre2->compiled_expr == NULL)
1422 {
1423 - if (PCRESetup(sc, rule, pcre))
1424 + if (PCRE2Setup(sc, rule, pcre2))
1425 {
1426 rule->initialized = 0;
1427 FreeOneRule(rule);
1428 @@ -1120,18 +1120,18 @@ static void FreeOneRule(void *data)
1429
1430 case OPTION_TYPE_PCRE:
1431 {
1432 - PCREInfo *pcre = option->option_u.pcre;
1433 + PCRE2Info *pcre2 = option->option_u.pcre2;
1434
1435 - if (pcre->compiled_expr != NULL)
1436 + if (pcre2->match_context != NULL)
1437 {
1438 - free(pcre->compiled_expr);
1439 - pcre->compiled_expr = NULL;
1440 + pcre2_match_context_free(pcre2->match_context);
1441 + pcre2->match_context = NULL;
1442 }
1443
1444 - if (pcre->compiled_extra != NULL)
1445 + if (pcre2->compiled_expr != NULL)
1446 {
1447 - free(pcre->compiled_extra);
1448 - pcre->compiled_extra = NULL;
1449 + pcre2_code_free(pcre2->compiled_expr);
1450 + pcre2->compiled_expr = NULL;
1451 }
1452 }
1453
1454 --- a/src/dynamic-plugins/sf_engine/sf_snort_detection_engine.h
1455 +++ b/src/dynamic-plugins/sf_engine/sf_snort_detection_engine.h
1456 @@ -30,7 +30,7 @@
1457 #define SF_SNORT_DETECTION_ENGINE__H
1458
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;
1469 break;
1470 case OPTION_TYPE_PCRE:
1471 - relative = option->option_u.pcre->flags & CONTENT_RELATIVE;
1472 + relative = option->option_u.pcre2->flags & CONTENT_RELATIVE;
1473 break;
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;
1482
1483 if (cursor)
1484 startCursor = thisCursor = *cursor;
1485 @@ -736,7 +736,7 @@ int ruleMatchInternal(SFSnortPacket *p,
1486 origOffset = thisContentInfo->offset;
1487 break;
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;
1493 break;
1494 @@ -760,8 +760,8 @@ int ruleMatchInternal(SFSnortPacket *p,
1495 notFlag = rule->options[optIndex]->option_u.protectedContent->flags & NOT_FLAG;
1496 break;
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;
1502 break;
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
1507 @@ -30,7 +30,8 @@
1508 #ifndef SF_SNORT_PLUGIN_API_H_
1509 #define SF_SNORT_PLUGIN_API_H_
1510
1511 -#include "pcre.h"
1512 +#define PCRE2_CODE_UNIT_WIDTH 8
1513 +#include <pcre2.h>
1514 #include "stdio.h"
1515
1516 #ifndef WIN32
1517 @@ -211,26 +212,26 @@ typedef struct _CursorInfo
1518 } CursorInfo;
1519
1520 /*
1521 -pcre.h provides flags:
1522 +pcre2.h provides flags:
1523
1524 -PCRE_CASELESS
1525 -PCRE_MULTILINE
1526 -PCRE_DOTALL
1527 -PCRE_EXTENDED
1528 -PCRE_ANCHORED
1529 -PCRE_DOLLAR_ENDONLY
1530 -PCRE_UNGREEDY
1531 +PCRE2_CASELESS
1532 +PCRE2_MULTILINE
1533 +PCRE2_DOTALL
1534 +PCRE2_EXTENDED
1535 +PCRE2_ANCHORED
1536 +PCRE2_DOLLAR_ENDONLY
1537 +PCRE2_UNGREEDY
1538 */
1539
1540 -typedef struct _PCREInfo
1541 +typedef struct _PCRE2Info
1542 {
1543 char *expr;
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 */
1549 int32_t offset;
1550 -} PCREInfo;
1551 +} PCRE2Info;
1552
1553 #define FLOWBIT_SET 0x01
1554 #define FLOWBIT_UNSET 0x02
1555 @@ -393,7 +394,7 @@ typedef struct _RuleOption
1556 ContentInfo *content;
1557 ProtectedContentInfo *protectedContent;
1558 CursorInfo *cursor;
1559 - PCREInfo *pcre;
1560 + PCRE2Info *pcre2;
1561 FlowBitsInfo *flowBit;
1562 ByteData *byte;
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);
1576
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);
1585
1586 static inline int invertMatchResult(int retVal)
1587 {
1588 --- a/src/dynamic-plugins/sf_engine/sf_snort_plugin_pcre.c
1589 +++ b/src/dynamic-plugins/sf_engine/sf_snort_plugin_pcre.c
1590 @@ -25,13 +25,14 @@
1591 * Date: 5/2005
1592 *
1593 *
1594 - * PCRE operations for dynamic rule engine
1595 + * PCRE2 operations for dynamic rule engine
1596 */
1597 #ifdef HAVE_CONFIG_H
1598 #include "config.h"
1599 #endif
1600
1601 -#include "pcre.h"
1602 +#define PCRE2_CODE_UNIT_WIDTH 8
1603 +#include <pcre2.h>
1604 #include "sf_types.h"
1605 #include "snort_debug.h"
1606 #include "sf_dynamic_define.h"
1607 @@ -43,32 +44,38 @@
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 **);
1613
1614 -int PCRESetup(struct _SnortConfig *sc, Rule *rule, PCREInfo *pcreInfo)
1615 +int PCRE2Setup(struct _SnortConfig *sc, Rule *rule, PCRE2Info *pcre2Info)
1616 {
1617 - const char *error;
1618 - int erroffset;
1619 + size_t erroffset;
1620 + int errorcode;
1621
1622 - pcreInfo->compiled_expr = (void *)_ded.pcreCompile(pcreInfo->expr,
1623 - pcreInfo->compile_flags,
1624 - &error,
1625 + pcre2Info->compiled_expr = (void *)_ded.pcre2Compile(pcre2Info->expr,
1626 + pcre2Info->compile_flags,
1627 + &errorcode,
1628 &erroffset,
1629 NULL);
1630
1631 - if (!pcreInfo->compiled_expr)
1632 + if (!pcre2Info->compiled_expr)
1633 {
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);
1638 return -1;
1639 }
1640 - else
1641 +
1642 + pcre2Info->match_context = _ded.pcre2MatchContextCreate(NULL);
1643 + if (!pcre2Info->match_context)
1644 {
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);
1649 + return -1;
1650 }
1651
1652 - if (error)
1653 + errorcode = _ded.pcre2JITCompile(sc, pcre2Info->compiled_expr, pcre2Info->match_context, pcre2Info->compile_flags);
1654 + if (errorcode)
1655 {
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
1659 return -1;
1660 }
1661
1662 - _ded.pcreCapture(sc, pcreInfo->compiled_expr, pcreInfo->compiled_extra);
1663 + _ded.pcre2Capture(sc, pcre2Info->compiled_expr);
1664
1665
1666 return 0;
1667 }
1668
1669 /**
1670 - * * Wrapper for pcre_exec to expose ovector.
1671 + * * Wrapper for pcre2_match_data_create to run match_data.
1672 + * */
1673 +ENGINE_LINKAGE void *pcre2MatchDataCreateWrapper(void)
1674 +{
1675 + return _ded.pcre2MatchDataCreate(_ded.pcre2OvectorSize(), NULL);
1676 +}
1677 +
1678 +/**
1679 + * * Wrapper for pcre2_match_data_free to run match_data.
1680 + * */
1681 +ENGINE_LINKAGE void pcre2MatchDataFreeWrapper(void *match_data)
1682 +{
1683 + _ded.pcre2MatchDataFree(match_data);
1684 +}
1685 +
1686 +/**
1687 + * * Wrapper for pcre2_get_ovector_count to run match_data.
1688 + * */
1689 +ENGINE_LINKAGE int pcre2GetOvectorCountWrapper(void *match_data)
1690 +{
1691 + return _ded.pcre2GetOvectorCount(match_data);
1692 +}
1693 +
1694 +/**
1695 + * * Wrapper for pcre2_get_ovector_pointer to run match_data.
1696 * */
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)
1700 +{
1701 + return _ded.pcre2GetOvectorPointer(match_data);
1702 +}
1703 +
1704 +/**
1705 + * * Wrapper for pcre2_match to run match_data.
1706 + * */
1707 +ENGINE_LINKAGE int pcre2ExecWrapper(const PCRE2Info *pcre2_info, const char *buf, int len, int start_offset,
1708 + int options, const void *match_data)
1709 {
1710 int result;
1711 int matched;
1712
1713 - if(pcre_info == NULL
1714 + if(pcre2_info == NULL
1715 || buf == NULL
1716 || len <= 0
1717 || start_offset < 0
1718 || start_offset >= len
1719 - || ovector == NULL)
1720 + || match_data == NULL)
1721 {
1722 return 0;
1723 }
1724
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 */
1736
1737 if(result >= 0)
1738 {
1739 matched = 1;
1740 }
1741 - else if(result == PCRE_ERROR_NOMATCH)
1742 + else if(result == PCRE2_ERROR_NOMATCH)
1743 {
1744 matched = 0;
1745 }
1746 else
1747 {
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););
1750 return 0;
1751 }
1752
1753 @@ -128,7 +166,7 @@ ENGINE_LINKAGE int pcreExecWrapper(const
1754 }
1755
1756 /*
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
1764
1765 /**
1766 - * Perform a search of the PCRE data.
1767 + * Perform a search of the PCRE2 data.
1768 *
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
1772 *
1773 * @return 1 when we find the string, 0 when we don't (unless we've been passed a flag to invert)
1774 */
1775 -static int pcre_test(const PCREInfo *pcre_info,
1776 +static int pcre2_test(const PCRE2Info *pcre2_info,
1777 const char *buf,
1778 int len,
1779 int start_offset,
1780 int *found_offset)
1781 {
1782 + void *match_data;
1783 + size_t *ovector;
1784 int matched;
1785 int result;
1786
1787 - int *ovector;
1788 - int ovector_size;
1789 -
1790 - _ded.pcreOvectorInfo(&ovector, &ovector_size);
1791 -
1792 - if(pcre_info == NULL
1793 + if(pcre2_info == NULL
1794 || buf == NULL
1795 || len <= 0
1796 || start_offset < 0
1797 @@ -174,50 +209,59 @@ static int pcre_test(const PCREInfo *pcr
1798 return 0;
1799 }
1800
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"););
1805 + return 0;
1806 + }
1807 +
1808 *found_offset = -1;
1809
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 */
1821
1822 if(result >= 0)
1823 {
1824 matched = 1;
1825 }
1826 - else if(result == PCRE_ERROR_NOMATCH)
1827 + else if(result == PCRE2_ERROR_NOMATCH)
1828 {
1829 matched = 0;
1830 }
1831 else
1832 {
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););
1836 return 0;
1837 }
1838
1839 if (found_offset)
1840 {
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););
1846 }
1847
1848 + _ded.pcre2MatchDataFree(match_data);
1849 return matched;
1850 }
1851
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)
1854 {
1855 if (pcre_info->flags & NOT_FLAG)
1856 return invertMatchResult(pcreMatchInternal(p, pcre_info, cursor));
1857 return pcreMatchInternal(p, pcre_info, cursor);
1858 }
1859
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)
1862 {
1863 const uint8_t *buffer_start;
1864 int buffer_len;
1865 @@ -295,7 +339,7 @@ static int pcreMatchInternal(void *p, PC
1866 }
1867
1868
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);
1871
1872 if (pcre_found)
1873 {
1874 --- a/src/dynamic-preprocessors/appid/luaDetectorApi.c
1875 +++ b/src/dynamic-preprocessors/appid/luaDetectorApi.c
1876 @@ -38,7 +38,8 @@
1877 #include "luaDetectorModule.h"
1878 #include "luaDetectorApi.h"
1879 #include "luaDetectorFlowApi.h"
1880 -#include <pcre.h>
1881 +#define PCRE2_CODE_UNIT_WIDTH 8
1882 +#include <pcre2.h>
1883 #include "httpCommon.h"
1884 #include "sf_multi_mpse.h"
1885 #include "fw_appid.h"
1886 @@ -54,7 +55,6 @@
1887 #include "detector_cip.h"
1888
1889 #define DETECTOR "Detector"
1890 -#define OVECCOUNT 30 /* should be a multiple of 3 */
1891 #define URL_LIST_STEP_SIZE 5000
1892
1893 typedef enum {
1894 @@ -1355,7 +1355,7 @@ static int Detector_getPacketDir(
1895 return 1;
1896 }
1897
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.
1901 *
1902 * @param Lua_State* - Lua state variable.
1903 @@ -1371,12 +1371,15 @@ static int Detector_getPcreGroups(
1904 Detector *detector;
1905 char *pattern;
1906 unsigned int offset;
1907 - pcre *re;
1908 - int ovector[OVECCOUNT];
1909 - const char *error;
1910 - int erroffset;
1911 + pcre2_code *re;
1912 + pcre2_match_data *match_data;
1913 + PCRE2_UCHAR error[128];
1914 + int errorcode;
1915 + PCRE2_SIZE erroffset;
1916 int rc, i;
1917 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1918 + unsigned int oveccount;
1919 + size_t *ovector;
1920
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(
1924
1925 {
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 */
1940
1941 if (re == NULL)
1942 {
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);
1946 return 0;
1947 }
1948
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");
1952 + return 0;
1953 + }
1954
1955 /*pattern match against the subject string. */
1956 - rc = pcre_exec(
1957 + rc = pcre2_match(
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 */
1969 -
1970 + match_data, /*output vector for substring information */
1971 + NULL); /*number of elements in the output vector */
1972
1973 if (rc < 0)
1974 {
1975 /*Matching failed: clubbing PCRE_ERROR_NOMATCH with other errors. */
1976 - pcre_free(re);
1977 + pcre2_match_data_free(match_data);
1978 + pcre2_code_free(re);
1979 return 0;
1980 }
1981
1982 /*Match succeded */
1983
1984 /*printf("\nMatch succeeded at offset %d", ovector[0]); */
1985 - pcre_free(re);
1986
1987 + oveccount = pcre2_get_ovector_count(match_data);
1988 + ovector = pcre2_get_ovector_pointer(match_data);
1989
1990 if (rc == 0)
1991 {
1992 /*overflow of matches */
1993 - rc = OVECCOUNT/3;
1994 + rc = oveccount/3;
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);
1997 }
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]);
2000 }
2001
2002 + pcre2_match_data_free(match_data);
2003 + pcre2_code_free(re);
2004 +
2005 return rc;
2006 }
2007
2008 --- a/src/dynamic-preprocessors/imap/snort_imap.h
2009 +++ b/src/dynamic-preprocessors/imap/snort_imap.h
2010 @@ -38,7 +38,8 @@
2011
2012 /* Includes ***************************************************************/
2013
2014 -#include <pcre.h>
2015 +#define PCRE2_CODE_UNIT_WIDTH 8
2016 +#include <pcre2.h>
2017
2018 #include "sf_snort_packet.h"
2019 #include "imap_config.h"
2020 @@ -216,8 +217,7 @@ typedef struct _IMAPMimeBoundary
2021
2022 typedef struct _IMAPPcre
2023 {
2024 - pcre *re;
2025 - pcre_extra *pe;
2026 + pcre2_code *re;
2027
2028 } IMAPPcre;
2029
2030 --- a/src/dynamic-preprocessors/pop/snort_pop.h
2031 +++ b/src/dynamic-preprocessors/pop/snort_pop.h
2032 @@ -38,7 +38,8 @@
2033
2034 /* Includes ***************************************************************/
2035
2036 -#include <pcre.h>
2037 +#define PCRE2_CODE_UNIT_WIDTH 8
2038 +#include <pcre2.h>
2039
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
2044 @@ -39,7 +39,8 @@
2045
2046 /* Includes ***************************************************************/
2047
2048 -#include <pcre.h>
2049 +#define PCRE2_CODE_UNIT_WIDTH 8
2050 +#include <pcre2.h>
2051
2052 #include "sf_snort_packet.h"
2053 #include "ssl.h"
2054 --- a/src/snort.c
2055 +++ b/src/snort.c
2056 @@ -4449,9 +4449,6 @@ void SnortConfFree(SnortConfig *sc)
2057
2058 OtnxMatchDataFree(sc->omd);
2059
2060 - if (sc->pcre_ovector != NULL)
2061 - free(sc->pcre_ovector);
2062 -
2063 if ( sc->event_queue_config )
2064 EventQueueConfigFree(sc->event_queue_config);
2065
2066 --- a/src/snort.h
2067 +++ b/src/snort.h
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;
2074
2075 #ifdef PERF_PROFILING
2076 --- a/src/util.c
2077 +++ b/src/util.c
2078 @@ -78,7 +78,8 @@ static struct mallinfo mi;
2079 #include "plugbase.h"
2080 #include "sf_types.h"
2081 #include "sflsq.h"
2082 -#include "pcre.h"
2083 +#define PCRE2_CODE_UNIT_WIDTH 8
2084 +#include "pcre2.h"
2085 #include "mpse.h"
2086 #include "ppm.h"
2087 #include "active.h"
2088 @@ -175,7 +176,7 @@ double CalcPct(uint64_t cnt, uint64_t to
2089 int DisplayBanner(void)
2090 {
2091 const char * info;
2092 - const char * pcre_ver;
2093 + PCRE2_UCHAR buffer[32];
2094 const char * zlib_ver;
2095
2096 info = getenv("HOSTTYPE");
2097 @@ -184,7 +185,7 @@ int DisplayBanner(void)
2098 info="";
2099 }
2100
2101 - pcre_ver = pcre_version();
2102 + pcre2_config(PCRE2_CONFIG_VERSION, buffer);
2103 zlib_ver = zlib_version;
2104
2105 LogMessage("\n");
2106 @@ -204,7 +205,7 @@ int DisplayBanner(void)
2107 #ifdef HAVE_PCAP_LIB_VERSION
2108 LogMessage(" Using %s\n", pcap_lib_version());
2109 #endif
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);
2113 LogMessage("\n");
2114