]> TLD Linux GIT Repositories - packages/syslog-ng.git/blob - pcre2.patch
- fix obsoleted keyword stats_freq in config files
[packages/syslog-ng.git] / pcre2.patch
1 diff -ur syslog-ng-syslog-ng-4.2.0.orig/CMakeLists.txt syslog-ng-syslog-ng-4.2.0/CMakeLists.txt
2 --- syslog-ng-syslog-ng-4.2.0.orig/CMakeLists.txt       2023-05-10 16:55:07.000000000 +0200
3 +++ syslog-ng-syslog-ng-4.2.0/CMakeLists.txt    2023-07-19 02:12:21.375815517 +0200
4 @@ -272,7 +272,7 @@
5  include(openssl_functions)
6  openssl_set_defines()
7  
8 -pkg_check_modules(LIBPCRE REQUIRED libpcre)
9 +pkg_check_modules(LIBPCRE REQUIRED libpcre2-8)
10  
11  if (WRAP_FOUND)
12    set(SYSLOG_NG_ENABLE_TCP_WRAPPER 1)
13 diff -ur syslog-ng-syslog-ng-4.2.0.orig/configure.ac syslog-ng-syslog-ng-4.2.0/configure.ac
14 --- syslog-ng-syslog-ng-4.2.0.orig/configure.ac 2023-05-10 16:55:07.000000000 +0200
15 +++ syslog-ng-syslog-ng-4.2.0/configure.ac      2023-07-19 02:12:21.375815517 +0200
16 @@ -48,7 +48,7 @@
17  IVYKIS_MIN_VERSION="0.36.1"
18  IVYKIS_UPDATED_VERSION="0.39"
19  JSON_C_MIN_VERSION="0.9"
20 -PCRE_MIN_VERSION="6.1"
21 +PCRE2_MIN_VERSION="10.0"
22  LMC_MIN_VERSION="1.0.0"
23  LRMQ_MIN_VERSION="0.0.1"
24  LRC_MIN_VERSION="1.6.0"
25 @@ -1046,9 +1046,10 @@
26          LIBS="$old_LIBS"
27  fi
28  
29 -PKG_CHECK_MODULES(PCRE, libpcre >= $PCRE_MIN_VERSION,, PCRE_LIBS="")
30 -if test -z "$PCRE_LIBS"; then
31 -       AC_MSG_ERROR(Cannot find pcre version >= $PCRE_MIN_VERSION it is a hard dependency from syslog-ng 3.6 onwards)
32 +PKG_CHECK_MODULES(PCRE2, libpcre2-8 >= $PCRE2_MIN_VERSION,, PCRE2_LIBS="")
33 +
34 +if test test -z "$PCRE2_LIBS"; then
35 +       AC_MSG_ERROR(Cannot find pcre2 version >= $PCRE2_MIN_VERSION which is a hard dependency from syslog-ng 3.6 onwards)
36  fi
37  
38  dnl ***************************************************************************
39 @@ -1846,7 +1847,7 @@
40  python_moduledir="$moduledir"/python
41  python_sysconf_moduledir="${sysconfdir}/python"
42  
43 -CPPFLAGS="$CPPFLAGS $GLIB_CFLAGS $EVTLOG_CFLAGS $PCRE_CFLAGS $OPENSSL_CFLAGS $LIBNET_CFLAGS $LIBDBI_CFLAGS $IVYKIS_CFLAGS $LIBCAP_CFLAGS -D_GNU_SOURCE -D_DEFAULT_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
44 +CPPFLAGS="$CPPFLAGS $GLIB_CFLAGS $EVTLOG_CFLAGS $PCRE2_CFLAGS $OPENSSL_CFLAGS $LIBNET_CFLAGS $LIBDBI_CFLAGS $IVYKIS_CFLAGS $LIBCAP_CFLAGS -D_GNU_SOURCE -D_DEFAULT_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
45  
46  ########################################################
47  ## NOTES: on how syslog-ng is linked
48 @@ -1894,7 +1895,7 @@
49  MODULE_DEPS_LIBS="\$(top_builddir)/lib/libsyslog-ng.la"
50  
51  if test "x$linking_mode" = "xdynamic"; then
52 -       SYSLOGNG_DEPS_LIBS="$LIBS $BASE_LIBS $GLIB_LIBS $EVTLOG_LIBS $SECRETSTORAGE_LIBS $RESOLV_LIBS $LIBCAP_LIBS $PCRE_LIBS $REGEX_LIBS $DL_LIBS"
53 +       SYSLOGNG_DEPS_LIBS="$LIBS $BASE_LIBS $GLIB_LIBS $EVTLOG_LIBS $SECRETSTORAGE_LIBS $RESOLV_LIBS $LIBCAP_LIBS $PCRE2_LIBS $REGEX_LIBS $DL_LIBS"
54  
55         if test "x$with_ivykis" = "xinternal"; then
56                 # when using the internal ivykis, we're linking it statically into libsyslog-ng.so
57 @@ -1913,8 +1914,8 @@
58         # syslog-ng binary is linked with the default link command (e.g. libtool)
59         SYSLOGNG_LINK='$(LINK)'
60  else
61 -       SYSLOGNG_DEPS_LIBS="$LIBS $BASE_LIBS $RESOLV_LIBS $EVTLOG_NO_LIBTOOL_LIBS $SECRETSTORAGE_NO_LIBTOOL_LIBS $LD_START_STATIC -Wl,${WHOLE_ARCHIVE_OPT} $GLIB_LIBS $PCRE_LIBS $REGEX_LIBS  -Wl,${NO_WHOLE_ARCHIVE_OPT} $IVYKIS_NO_LIBTOOL_LIBS $LD_END_STATIC $LIBCAP_LIBS $DL_LIBS"
62 -       TOOL_DEPS_LIBS="$LIBS $BASE_LIBS $GLIB_LIBS $EVTLOG_LIBS $SECRETSTORAGE_LIBS $RESOLV_LIBS $LIBCAP_LIBS $PCRE_LIBS $REGEX_LIBS $IVYKIS_LIBS $DL_LIBS"
63 +       SYSLOGNG_DEPS_LIBS="$LIBS $BASE_LIBS $RESOLV_LIBS $EVTLOG_NO_LIBTOOL_LIBS $SECRETSTORAGE_NO_LIBTOOL_LIBS $LD_START_STATIC -Wl,${WHOLE_ARCHIVE_OPT} $GLIB_LIBS $PCRE2_LIBS $REGEX_LIBS  -Wl,${NO_WHOLE_ARCHIVE_OPT} $IVYKIS_NO_LIBTOOL_LIBS $LD_END_STATIC $LIBCAP_LIBS $DL_LIBS"
64 +       TOOL_DEPS_LIBS="$LIBS $BASE_LIBS $GLIB_LIBS $EVTLOG_LIBS $SECRETSTORAGE_LIBS $RESOLV_LIBS $LIBCAP_LIBS $PCRE2_LIBS $REGEX_LIBS $IVYKIS_LIBS $DL_LIBS"
65         CORE_DEPS_LIBS=""
66  
67         # bypass libtool in case we want to do mixed linking because it
68 diff -ur syslog-ng-syslog-ng-4.2.0.orig/lib/compat/pcre.h syslog-ng-syslog-ng-4.2.0/lib/compat/pcre.h
69 --- syslog-ng-syslog-ng-4.2.0.orig/lib/compat/pcre.h    2023-05-10 16:55:07.000000000 +0200
70 +++ syslog-ng-syslog-ng-4.2.0/lib/compat/pcre.h 2023-07-19 02:12:21.376815531 +0200
71 @@ -26,18 +26,8 @@
72  #define COMPAT_PCRE_H_INCLUDED
73  
74  #include "compat/compat.h"
75 -#include <pcre.h>
76  
77 -#ifndef PCRE_CONFIG_JIT
78 -#define pcre_free_study pcre_free
79 -#endif
80 -
81 -#ifndef PCRE_STUDY_JIT_COMPILE
82 -#define PCRE_STUDY_JIT_COMPILE 0
83 -#endif
84 -
85 -#ifndef PCRE_NEWLINE_ANYCRLF
86 -#define PCRE_NEWLINE_ANYCRLF 0
87 -#endif
88 +#define PCRE2_CODE_UNIT_WIDTH 8
89 +#include <pcre2.h>
90  
91  #endif /* COMPAT_PCRE_H_INCLUDED */
92 diff -ur syslog-ng-syslog-ng-4.2.0.orig/lib/filter/tests/test_filters_regexp.c syslog-ng-syslog-ng-4.2.0/lib/filter/tests/test_filters_regexp.c
93 --- syslog-ng-syslog-ng-4.2.0.orig/lib/filter/tests/test_filters_regexp.c       2023-05-10 16:55:07.000000000 +0200
94 +++ syslog-ng-syslog-ng-4.2.0/lib/filter/tests/test_filters_regexp.c    2023-07-19 02:12:21.376815531 +0200
95 @@ -53,12 +53,6 @@
96    const gchar *value;
97  } FilterParamRegexp;
98  
99 -static gboolean
100 -check_pcre_version_is_atleast(const gchar *version)
101 -{
102 -  return strncmp(pcre_version(), version, strlen(version)) >= 0;
103 -}
104 -
105  Test(filter, create_pcre_regexp_filter)
106  {
107    cr_assert_eq(create_pcre_regexp_filter(LM_V_PROGRAM, "((", 0), NULL);
108 @@ -70,8 +64,7 @@
109    cr_assert_eq(create_pcre_regexp_filter(LM_V_HOST, "(?iana", 0), NULL);
110    cr_assert_eq(create_pcre_regexp_match("((", 0), NULL);
111    cr_assert_eq(create_pcre_regexp_match("(?P<foo_123", 0), NULL);  // Unterminated group identifier
112 -  if (check_pcre_version_is_atleast("8.34"))
113 -    cr_assert_eq(create_pcre_regexp_match("(?P<1>a)", 0), NULL);  // Begins with a digit
114 +  cr_assert_eq(create_pcre_regexp_match("(?P<1>a)", 0), NULL);  // Begins with a digit
115    cr_assert_eq(create_pcre_regexp_match("(?P<!>a)", 0), NULL);  // Begins with an illegal char
116    cr_assert_eq(create_pcre_regexp_match("(?P<foo!>a)", 0), NULL);  // Ends with an illegal char
117    cr_assert_eq(create_pcre_regexp_match("\\1", 0), NULL);  // Backreference
118 diff -ur syslog-ng-syslog-ng-4.2.0.orig/lib/logmatcher.c syslog-ng-syslog-ng-4.2.0/lib/logmatcher.c
119 --- syslog-ng-syslog-ng-4.2.0.orig/lib/logmatcher.c     2023-05-10 16:55:07.000000000 +0200
120 +++ syslog-ng-syslog-ng-4.2.0/lib/logmatcher.c  2023-07-19 02:12:21.376815531 +0200
121 @@ -281,87 +281,82 @@
122  typedef struct _LogMatcherPcreRe
123  {
124    LogMatcher super;
125 -  pcre *pattern;
126 -  pcre_extra *extra;
127 +  pcre2_code *pattern;
128    gint match_options;
129    gchar *nv_prefix;
130    gint nv_prefix_len;
131  } LogMatcherPcreRe;
132  
133  static gboolean
134 -_compile_pcre_regexp(LogMatcherPcreRe *self, const gchar *re, GError **error)
135 +_compile_pcre2_regexp(LogMatcherPcreRe *self, const gchar *re, GError **error)
136  {
137    gint rc;
138 -  const gchar *errptr;
139 -  gint erroffset;
140    gint flags = 0;
141  
142    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
143  
144    if (self->super.flags & LMF_ICASE)
145 -    flags |= PCRE_CASELESS;
146 +    flags |= PCRE2_CASELESS;
147  
148    if (self->super.flags & LMF_NEWLINE)
149      {
150 -      if (!PCRE_NEWLINE_ANYCRLF)
151 +      if (!PCRE2_NEWLINE_ANYCRLF)
152          msg_warning("syslog-ng was compiled against an old PCRE which doesn't support the 'newline' flag");
153 -      flags |= PCRE_NEWLINE_ANYCRLF;
154 +      flags |= PCRE2_NEWLINE_ANYCRLF;
155      }
156    if (self->super.flags & LMF_UTF8)
157      {
158        gint support;
159 -      flags |= PCRE_UTF8 | PCRE_NO_UTF8_CHECK;
160 -      self->match_options |= PCRE_NO_UTF8_CHECK;
161 +      flags |= PCRE2_UTF | PCRE2_NO_UTF_CHECK;
162 +      self->match_options |= PCRE2_NO_UTF_CHECK;
163  
164 -      pcre_config(PCRE_CONFIG_UTF8, &support);
165 +      pcre2_config(PCRE2_CONFIG_UNICODE, &support);
166        if (!support)
167          {
168 -          g_set_error(error, LOG_TEMPLATE_ERROR, 0, "PCRE library is compiled without UTF8 support and utf8 flag was present");
169 +          g_set_error(error, LOG_TEMPLATE_ERROR, 0, "PCRE library is compiled without unicode support and utf8 flag was present");
170            return FALSE;
171          }
172  
173 -      pcre_config(PCRE_CONFIG_UNICODE_PROPERTIES, &support);
174 -      if (!support)
175 -        {
176 -          g_set_error(error, LOG_TEMPLATE_ERROR, 0,
177 -                      "PCRE library is compiled without UTF8 properties support and utf8 flag was present");
178 -          return FALSE;
179 -        }
180      }
181    if (self->super.flags & LMF_DUPNAMES)
182      {
183 -      if (!PCRE_DUPNAMES)
184 +      if (!PCRE2_DUPNAMES)
185          msg_warning("syslog-ng was compiled against an old PCRE which doesn't support the 'dupnames' flag");
186 -      flags |= PCRE_DUPNAMES;
187 +      flags |= PCRE2_DUPNAMES;
188      }
189  
190    /* compile the regexp */
191 -  self->pattern = pcre_compile2(re, flags, &rc, &errptr, &erroffset, NULL);
192 +  PCRE2_SIZE error_offset;
193 +
194 +  self->pattern = pcre2_compile((PCRE2_SPTR) re, PCRE2_ZERO_TERMINATED, flags, &rc, &error_offset, NULL);
195    if (!self->pattern)
196      {
197 +      PCRE2_UCHAR error_message[128];
198 +
199 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
200        g_set_error(error, LOG_TEMPLATE_ERROR, 0, "Failed to compile PCRE expression >>>%s<<< `%s' at character %d",
201 -                  re, errptr, erroffset);
202 +                  re, error_message, (gint) error_offset);
203        return FALSE;
204      }
205    return TRUE;
206  }
207  
208  static gboolean
209 -_study_pcre_regexp(LogMatcherPcreRe *self, const gchar *re, GError **error)
210 +_jit_pcre2_regexp(LogMatcherPcreRe *self, const gchar *re, GError **error)
211  {
212 -  const gchar *errptr;
213 -  gint options = 0;
214 -
215 -  if ((self->super.flags & LMF_DISABLE_JIT) == 0)
216 -    options |= PCRE_STUDY_JIT_COMPILE;
217 +  if ((self->super.flags & LMF_DISABLE_JIT))
218 +    return TRUE;
219  
220    /* optimize regexp */
221 -  self->extra = pcre_study(self->pattern, options, &errptr);
222 -  if (errptr != NULL)
223 +  gint rc = pcre2_jit_compile(self->pattern, PCRE2_JIT_COMPLETE);
224 +  if (rc < 0)
225      {
226 -      g_set_error(error, LOG_TEMPLATE_ERROR, 0, "Failed to optimize regular expression >>>%s<<< `%s'",
227 -                  re, errptr);
228 -      return FALSE;
229 +      PCRE2_UCHAR error_message[128];
230 +
231 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
232 +      msg_warning("Failed to JIT compile regular expression, you might want to use flags(disable-jit)",
233 +                  evt_tag_str("regexp", re),
234 +                  evt_tag_str("error", (gchar *) error_message));
235      }
236    return TRUE;
237  }
238 @@ -374,10 +369,10 @@
239    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
240    log_matcher_store_pattern(s, re);
241  
242 -  if (!_compile_pcre_regexp(self, re, error))
243 +  if (!_compile_pcre2_regexp(self, re, error))
244      return FALSE;
245  
246 -  if (!_study_pcre_regexp(self, re, error))
247 +  if (!_jit_pcre2_regexp(self, re, error))
248      return FALSE;
249  
250    return TRUE;
251 @@ -388,8 +383,7 @@
252    NVHandle source_handle;
253    const gchar *source_value;
254    gssize source_value_len;
255 -  gint *matches;
256 -  gint num_matches;
257 +  pcre2_match_data *match_data;
258  } LogMatcherPcreMatchResult;
259  
260  static inline void
261 @@ -434,11 +428,13 @@
262  log_matcher_pcre_re_feed_backrefs(LogMatcherPcreRe *self, LogMessage *msg, LogMatcherPcreMatchResult *result)
263  {
264    gint i;
265 +  guint32 num_matches = pcre2_get_ovector_count(result->match_data);
266 +  PCRE2_SIZE *matches = pcre2_get_ovector_pointer(result->match_data);
267  
268 -  for (i = 0; i < (LOGMSG_MAX_MATCHES) && i < result->num_matches; i++)
269 +  for (i = 0; i < (LOGMSG_MAX_MATCHES) && i < num_matches; i++)
270      {
271 -      gint begin_index = result->matches[2 * i];
272 -      gint end_index = result->matches[2 * i + 1];
273 +      gint begin_index = matches[2 * i];
274 +      gint end_index = matches[2 * i + 1];
275  
276        if (begin_index < 0 || end_index < 0)
277          continue;
278 @@ -446,11 +442,11 @@
279        log_matcher_pcre_re_feed_value(self, msg, log_msg_get_match_handle(i), result, begin_index, end_index);
280      }
281    if (log_msg_is_handle_match(result->source_handle) &&
282 -      log_msg_get_match_index(result->source_handle) >= result->num_matches)
283 +      log_msg_get_match_index(result->source_handle) >= num_matches)
284      {
285        log_matcher_pcre_re_save_source_value_to_avoid_clobbering(result);
286      }
287 -  log_msg_truncate_matches(msg, result->num_matches);
288 +  log_msg_truncate_matches(msg, num_matches);
289  }
290  
291  static void
292 @@ -458,18 +454,20 @@
293  {
294    gchar *name_table = NULL;
295    gint i = 0;
296 -  gint namecount = 0;
297 -  gint name_entry_size = 0;
298 +  guint32 namecount = 0;
299 +  guint32 name_entry_size = 0;
300  
301 -  pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_NAMECOUNT, &namecount);
302 +  pcre2_pattern_info(self->pattern, PCRE2_INFO_NAMECOUNT, &namecount);
303    if (namecount > 0)
304      {
305 +      PCRE2_SIZE *matches = pcre2_get_ovector_pointer(result->match_data);
306 +
307        gchar *tabptr;
308        /* Before we can access the substrings, we must extract the table for
309           translating names to numbers, and the size of each entry in the table.
310         */
311 -      pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_NAMETABLE, &name_table);
312 -      pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_NAMEENTRYSIZE, &name_entry_size);
313 +      pcre2_pattern_info(self->pattern, PCRE2_INFO_NAMETABLE, &name_table);
314 +      pcre2_pattern_info(self->pattern, PCRE2_INFO_NAMEENTRYSIZE, &name_entry_size);
315        /* Now we can scan the table and, for each entry, print the number, the name,
316           and the substring itself.
317         */
318 @@ -480,8 +478,8 @@
319        for (i = 0; i < namecount; i++, tabptr += name_entry_size)
320          {
321            int n = (tabptr[0] << 8) | tabptr[1];
322 -          gint begin_index = result->matches[2 * n];
323 -          gint end_index = result->matches[2 * n + 1];
324 +          gint begin_index = matches[2 * n];
325 +          gint end_index = matches[2 * n + 1];
326            const gchar *namedgroup_name = tabptr + 2;
327  
328            if (begin_index < 0 || end_index < 0)
329 @@ -502,30 +500,28 @@
330    LogMatcherPcreRe *self = (LogMatcherPcreRe *) s;
331    LogMatcherPcreMatchResult result;
332    gint rc;
333 +  gboolean res = TRUE;
334  
335    if (value_len == -1)
336      value_len = strlen(value);
337  
338 -  if (pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_CAPTURECOUNT, &result.num_matches) < 0)
339 -    g_assert_not_reached();
340 -  if (result.num_matches > LOGMSG_MAX_MATCHES)
341 -    result.num_matches = LOGMSG_MAX_MATCHES;
342 -
343 -  gsize matches_size = 3 * (result.num_matches + 1);
344 -  result.matches = g_alloca(matches_size * sizeof(gint));
345 +  result.match_data = pcre2_match_data_create_from_pattern(self->pattern, NULL);
346    result.source_value = value;
347    result.source_value_len = value_len;
348    result.source_handle = value_handle;
349  
350 -  rc = pcre_exec(self->pattern, self->extra,
351 -                 result.source_value, result.source_value_len,
352 -                 0, self->match_options,
353 -                 result.matches, matches_size);
354 +  rc = pcre2_match(self->pattern,
355 +                   (PCRE2_SPTR) result.source_value,
356 +                   (PCRE2_SIZE) result.source_value_len,
357 +                   (PCRE2_SIZE) 0,
358 +                   self->match_options,
359 +                   result.match_data,
360 +                   NULL);
361    if (rc < 0)
362      {
363        switch (rc)
364          {
365 -        case PCRE_ERROR_NOMATCH:
366 +        case PCRE2_ERROR_NOMATCH:
367            break;
368  
369          default:
370 @@ -534,22 +530,22 @@
371                      evt_tag_int("error_code", rc));
372            break;
373          }
374 -      return FALSE;
375 +      res = FALSE;
376      }
377 -  if (rc == 0)
378 +  else if (rc == 0)
379      {
380 -      msg_error("Error while storing matching substrings");
381 +      msg_error("Error while storing matching substrings, more than 256 capture groups encountered");
382      }
383    else
384      {
385 -      result.num_matches = rc;
386        if ((s->flags & LMF_STORE_MATCHES))
387          {
388            log_matcher_pcre_re_feed_backrefs(self, msg, &result);
389            log_matcher_pcre_re_feed_named_substrings(self, msg, &result);
390          }
391      }
392 -  return TRUE;
393 +  pcre2_match_data_free(result.match_data);
394 +  return res;
395  }
396  
397  static gchar *
398 @@ -559,24 +555,19 @@
399    LogMatcherPcreRe *self = (LogMatcherPcreRe *) s;
400    LogMatcherPcreMatchResult result;
401    GString *new_value = NULL;
402 -  gsize matches_size;
403    gint rc;
404    gint start_offset, last_offset;
405    gint options;
406    gboolean last_match_was_empty;
407  
408 -  if (pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_CAPTURECOUNT, &result.num_matches) < 0)
409 -    g_assert_not_reached();
410 -  if (result.num_matches > LOGMSG_MAX_MATCHES)
411 -    result.num_matches = LOGMSG_MAX_MATCHES;
412 +  result.match_data = pcre2_match_data_create_from_pattern(self->pattern, NULL);
413 +  PCRE2_SIZE *matches = pcre2_get_ovector_pointer(result.match_data);
414  
415 -  matches_size = 3 * (result.num_matches + 1);
416 -  result.matches = g_alloca(matches_size * sizeof(gint));
417  
418    /* we need zero initialized offsets for the last match as the
419     * algorithm tries uses that as the base position */
420  
421 -  result.matches[0] = result.matches[1] = result.matches[2] = 0;
422 +  matches[0] = matches[1] = 0;
423  
424    if (value_len == -1)
425      value_len = strlen(value);
426 @@ -596,7 +587,7 @@
427         * advanced).
428         *
429         * A zero-length match can be as simple as "a*" which will be
430 -       * returned unless PCRE_NOTEMPTY is specified.
431 +       * returned unless PCRE2_NOTEMPTY is specified.
432         *
433         * By supporting zero-length matches, we basically make it
434         * possible to insert replacement between each incoming
435 @@ -617,17 +608,21 @@
436             * to see if a non-empty match can be found.
437             */
438  
439 -          options = PCRE_NOTEMPTY | PCRE_ANCHORED;
440 +          options = PCRE2_NOTEMPTY | PCRE2_ANCHORED;
441          }
442        else
443          {
444            options = 0;
445          }
446  
447 -      rc = pcre_exec(self->pattern, self->extra,
448 -                     result.source_value, result.source_value_len,
449 -                     start_offset, (self->match_options | options), result.matches, matches_size);
450 -      if (rc < 0 && rc != PCRE_ERROR_NOMATCH)
451 +      rc = pcre2_match(self->pattern,
452 +                       (PCRE2_SPTR) result.source_value,
453 +                       (PCRE2_SIZE) result.source_value_len,
454 +                       start_offset,
455 +                       (self->match_options | options),
456 +                       result.match_data,
457 +                       NULL);
458 +      if (rc < 0 && rc != PCRE2_ERROR_NOMATCH)
459          {
460            msg_error("Error while matching regexp",
461                      evt_tag_int("error_code", rc));
462 @@ -635,7 +630,7 @@
463          }
464        else if (rc < 0)
465          {
466 -          if ((options & PCRE_NOTEMPTY) == 0)
467 +          if ((options & PCRE2_NOTEMPTY) == 0)
468              {
469                /* we didn't match, even when we permitted to match the
470                 * empty string. Nothing to find here, bail out */
471 @@ -651,31 +646,31 @@
472            last_match_was_empty = FALSE;
473            continue;
474          }
475 +      else if (rc == 0)
476 +        {
477 +          msg_error("Error while storing matching substrings, more than 256 capture groups encountered");
478 +          break;
479 +        }
480        else
481          {
482 -          /* if the output array was too small, truncate the number of
483 -             captures to LOGMSG_MAX_MATCHES */
484 -
485 -          if (rc == 0)
486 -            rc = matches_size / 3;
487 -
488 -          result.num_matches = rc;
489            log_matcher_pcre_re_feed_backrefs(self, msg, &result);
490            log_matcher_pcre_re_feed_named_substrings(self, msg, &result);
491  
492            if (!new_value)
493              new_value = g_string_sized_new(result.source_value_len);
494            /* append non-matching portion */
495 -          g_string_append_len(new_value, &result.source_value[last_offset], result.matches[0] - last_offset);
496 +          g_string_append_len(new_value, &result.source_value[last_offset], matches[0] - last_offset);
497            /* replacement */
498            log_template_append_format(replacement, msg, &DEFAULT_TEMPLATE_EVAL_OPTIONS, new_value);
499  
500 -          last_match_was_empty = (result.matches[0] == result.matches[1]);
501 -          start_offset = last_offset = result.matches[1];
502 +          last_match_was_empty = (matches[0] == matches[1]);
503 +          start_offset = last_offset = matches[1];
504          }
505      }
506    while (self->super.flags & LMF_GLOBAL && start_offset < result.source_value_len);
507  
508 +  pcre2_match_data_free(result.match_data);
509 +
510    if (new_value)
511      {
512        /* append the last literal */
513 @@ -691,8 +686,7 @@
514  log_matcher_pcre_re_free(LogMatcher *s)
515  {
516    LogMatcherPcreRe *self = (LogMatcherPcreRe *) s;
517 -  pcre_free_study(self->extra);
518 -  pcre_free(self->pattern);
519 +  pcre2_code_free(self->pattern);
520    log_matcher_free_method(s);
521  }
522  
523 diff -ur syslog-ng-syslog-ng-4.2.0.orig/lib/multi-line/multi-line-pattern.c syslog-ng-syslog-ng-4.2.0/lib/multi-line/multi-line-pattern.c
524 --- syslog-ng-syslog-ng-4.2.0.orig/lib/multi-line/multi-line-pattern.c  2023-05-10 16:55:07.000000000 +0200
525 +++ syslog-ng-syslog-ng-4.2.0/lib/multi-line/multi-line-pattern.c       2023-07-19 02:12:21.376815531 +0200
526 @@ -22,69 +22,105 @@
527   * COPYING for details.
528   */
529  #include "multi-line/multi-line-pattern.h"
530 +#include "messages.h"
531  
532  MultiLinePattern *
533  multi_line_pattern_compile(const gchar *regexp, GError **error)
534  {
535    MultiLinePattern *self = g_new0(MultiLinePattern, 1);
536 -  gint optflags = 0;
537    gint rc;
538 -  const gchar *errptr;
539 -  gint erroffset;
540 +  PCRE2_SIZE erroffset;
541  
542    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
543    self->ref_cnt = 1;
544  
545    /* compile the regexp */
546 -  self->pattern = pcre_compile2(regexp, 0, &rc, &errptr, &erroffset, NULL);
547 +  self->pattern = pcre2_compile((PCRE2_SPTR) regexp, PCRE2_ZERO_TERMINATED, 0, &rc, &erroffset, NULL);
548    if (!self->pattern)
549      {
550 -      g_set_error(error, 0, 0, "Error while compiling multi-line regexp as a PCRE expression, error=%s, error_at=%d", errptr,
551 -                  erroffset);
552 +      PCRE2_UCHAR error_message[128];
553 +
554 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
555 +      g_set_error(error, 0, 0,
556 +                  "Error while compiling multi-line regexp as a PCRE expression, error=%s, error_at=%" G_GSIZE_FORMAT,
557 +                  (gchar *) error_message, erroffset);
558        goto error;
559      }
560  
561 -#ifdef PCRE_STUDY_JIT_COMPILE
562 -  optflags = PCRE_STUDY_JIT_COMPILE;
563 -#endif
564 -
565    /* optimize regexp */
566 -  self->extra = pcre_study(self->pattern, optflags, &errptr);
567 -  if (errptr != NULL)
568 +  rc = pcre2_jit_compile(self->pattern, PCRE2_JIT_COMPLETE);
569 +  if (rc < 0)
570      {
571 -      g_set_error(error, 0, 0, "Error while studying multi-line regexp, error=%s", errptr);
572 -      goto error;
573 +      PCRE2_UCHAR error_message[128];
574 +
575 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
576 +      msg_warning("multi-line-pattern: Error while JIT compiling regular expression",
577 +                  evt_tag_str("regexp", regexp),
578 +                  evt_tag_str("error", (gchar *) error_message));
579      }
580  
581    return self;
582  error:
583    if (self->pattern)
584 -    pcre_free(self->pattern);
585 +    pcre2_code_free(self->pattern);
586    g_free(self);
587    return NULL;
588  }
589  
590  gint
591 -multi_line_pattern_find(MultiLinePattern *re, const guchar *str, gsize len, gint *matches, gint matches_num)
592 +multi_line_pattern_eval(MultiLinePattern *re, const guchar *str, gsize len, pcre2_match_data *match_data)
593  {
594 -  gint rc;
595 +  return pcre2_match(re->pattern, (PCRE2_SPTR) str, (PCRE2_SIZE) len, 0, 0, match_data, NULL);
596 +}
597  
598 +gboolean
599 +multi_line_pattern_find(MultiLinePattern *re, const guchar *str, gsize len, gint *start, gint *end)
600 +{
601    if (!re)
602 -    return -1;
603 +    return FALSE;
604 +
605 +  gboolean result = FALSE;
606 +  pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(re->pattern, NULL);
607 +
608  
609 -  rc = pcre_exec(re->pattern, re->extra, (const gchar *) str, len, 0, 0, matches, matches_num * 3);
610 -  return rc;
611 +  if (multi_line_pattern_eval(re, str, len, match_data) < 0)
612 +    goto exit;
613 +
614 +  guint32 num_matches = pcre2_get_ovector_count(match_data);
615 +  PCRE2_SIZE *matches = pcre2_get_ovector_pointer(match_data);
616 +
617 +  if (num_matches == 0)
618 +    goto exit;
619 +
620 +  *start = matches[0];
621 +  *end = matches[1];
622 +  result = TRUE;
623 +exit:
624 +  pcre2_match_data_free(match_data);
625 +  return result;
626  }
627  
628  gboolean
629  multi_line_pattern_match(MultiLinePattern *re, const guchar *str, gsize len)
630  {
631 -  gint match[3];
632 -  if (multi_line_pattern_find(re, str, len, match, 1) < 0)
633 +  if (!re)
634      return FALSE;
635 -  return match[0] >= 0;
636 -}
637  
638 +  gboolean result = FALSE;
639 +  pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(re->pattern, NULL);
640 +
641 +  if (multi_line_pattern_eval(re, str, len, match_data) < 0)
642 +    goto exit;
643 +
644 +  guint32 num_matches = pcre2_get_ovector_count(match_data);
645 +  PCRE2_SIZE *matches = pcre2_get_ovector_pointer(match_data);
646 +
647 +  result = num_matches > 0 && matches[0] >= 0;
648 +
649 +exit:
650 +  pcre2_match_data_free(match_data);
651 +  return result;
652 +}
653  
654  MultiLinePattern *
655  multi_line_pattern_ref(MultiLinePattern *self)
656 @@ -100,9 +136,7 @@
657    if (self && (--self->ref_cnt == 0))
658      {
659        if (self->pattern)
660 -        pcre_free(self->pattern);
661 -      if (self->extra)
662 -        pcre_free_study(self->extra);
663 +        pcre2_code_free(self->pattern);
664        g_free(self);
665      }
666  }
667 diff -ur syslog-ng-syslog-ng-4.2.0.orig/lib/multi-line/multi-line-pattern.h syslog-ng-syslog-ng-4.2.0/lib/multi-line/multi-line-pattern.h
668 --- syslog-ng-syslog-ng-4.2.0.orig/lib/multi-line/multi-line-pattern.h  2023-05-10 16:55:07.000000000 +0200
669 +++ syslog-ng-syslog-ng-4.2.0/lib/multi-line/multi-line-pattern.h       2023-07-19 02:12:21.376815531 +0200
670 @@ -33,11 +33,10 @@
671  struct _MultiLinePattern
672  {
673    gint ref_cnt;
674 -  pcre *pattern;
675 -  pcre_extra *extra;
676 +  pcre2_code *pattern;
677  };
678  
679 -gint multi_line_pattern_find(MultiLinePattern *re, const guchar *str, gsize len, gint *matches, gint matches_num);
680 +gboolean multi_line_pattern_find(MultiLinePattern *re, const guchar *str, gsize len, gint *start, gint *end);
681  gboolean multi_line_pattern_match(MultiLinePattern *re, const guchar *str, gsize len);
682  MultiLinePattern *multi_line_pattern_compile(const gchar *regexp, GError **error);
683  MultiLinePattern *multi_line_pattern_ref(MultiLinePattern *self);
684 diff -ur syslog-ng-syslog-ng-4.2.0.orig/lib/multi-line/regexp-multi-line.c syslog-ng-syslog-ng-4.2.0/lib/multi-line/regexp-multi-line.c
685 --- syslog-ng-syslog-ng-4.2.0.orig/lib/multi-line/regexp-multi-line.c   2023-05-10 16:55:07.000000000 +0200
686 +++ syslog-ng-syslog-ng-4.2.0/lib/multi-line/regexp-multi-line.c        2023-07-19 02:12:21.377815546 +0200
687 @@ -27,19 +27,21 @@
688  static gint
689  _prefix_garbage_get_offset_of_garbage(RegexpMultiLine *self, const guchar *line, gsize line_len)
690  {
691 -  gint match[3];
692 -  if (multi_line_pattern_find(self->garbage, line, line_len, match, 1) < 0)
693 +  gint start, end;
694 +
695 +  if (!multi_line_pattern_find(self->garbage, line, line_len, &start, &end))
696      return -1;
697 -  return match[0];
698 +  return start;
699  }
700  
701  static gint
702  _prefix_suffix_get_offset_of_garbage(RegexpMultiLine *self, const guchar *line, gsize line_len)
703  {
704 -  gint match[3];
705 -  if (multi_line_pattern_find(self->garbage, line, line_len, match, 1) < 0)
706 +  gint start, end;
707 +
708 +  if (!multi_line_pattern_find(self->garbage, line, line_len, &start, &end))
709      return -1;
710 -  return match[1];
711 +  return end;
712  }
713  
714  static gint
715 diff -ur syslog-ng-syslog-ng-4.2.0.orig/modules/basicfuncs/list-funcs.c syslog-ng-syslog-ng-4.2.0/modules/basicfuncs/list-funcs.c
716 --- syslog-ng-syslog-ng-4.2.0.orig/modules/basicfuncs/list-funcs.c      2023-05-10 16:55:07.000000000 +0200
717 +++ syslog-ng-syslog-ng-4.2.0/modules/basicfuncs/list-funcs.c   2023-07-19 02:12:21.377815546 +0200
718 @@ -354,8 +354,7 @@
719    StringMatchMode mode;
720    gchar *pattern;
721    GPatternSpec *glob;
722 -  pcre *pcre;
723 -  pcre_extra *pcre_extra;
724 +  pcre2_code *pcre;
725  } StringMatcher;
726  
727  static gboolean
728 @@ -369,33 +368,35 @@
729  static gboolean
730  string_matcher_prepare_pcre(StringMatcher *self)
731  {
732 -  const gchar *errptr;
733 -  gint erroffset;
734 +  PCRE2_SIZE erroffset;
735    gint rc;
736  
737 -  self->pcre = pcre_compile2(self->pattern, PCRE_ANCHORED, &rc, &errptr, &erroffset, NULL);
738 +  self->pcre = pcre2_compile((PCRE2_SPTR) self->pattern, PCRE2_ZERO_TERMINATED, PCRE2_ANCHORED, &rc, &erroffset, NULL);
739    if (!self->pcre)
740      {
741 +      PCRE2_UCHAR error_message[128];
742 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
743 +
744        msg_error("Error while compiling regular expression",
745                  evt_tag_str("regular_expression", self->pattern),
746                  evt_tag_str("error_at", &self->pattern[erroffset]),
747                  evt_tag_int("error_offset", erroffset),
748 -                evt_tag_str("error_message", errptr),
749 +                evt_tag_str("error_message", (gchar *) error_message),
750                  evt_tag_int("error_code", rc));
751        return FALSE;
752      }
753 -  self->pcre_extra = pcre_study(self->pcre, PCRE_STUDY_JIT_COMPILE, &errptr);
754 -  if (errptr)
755 +
756 +  /* optimize regexp */
757 +  rc = pcre2_jit_compile(self->pcre, PCRE2_JIT_COMPLETE);
758 +  if (rc < 0)
759      {
760 -      msg_error("Error while optimizing regular expression",
761 -                evt_tag_str("regular_expression", self->pattern),
762 -                evt_tag_str("error_message", errptr));
763 -      pcre_free(self->pcre);
764 -      if (self->pcre_extra)
765 -        pcre_free_study(self->pcre_extra);
766 -      return FALSE;
767 -    }
768 +      PCRE2_UCHAR error_message[128];
769  
770 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
771 +      msg_warning("$(list-search): Failed to JIT compile regular expression",
772 +                  evt_tag_str("regexp", self->pattern),
773 +                  evt_tag_str("error", (gchar *) error_message));
774 +    }
775    return TRUE;
776  }
777  
778 @@ -416,8 +417,11 @@
779  static gboolean
780  string_matcher_match_pcre(StringMatcher *self, const char *string, gsize string_len)
781  {
782 -  gint rc = pcre_exec(self->pcre, self->pcre_extra, string, string_len, 0, 0, NULL, 0);
783 -  if (rc == PCRE_ERROR_NOMATCH)
784 +  pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(self->pcre, NULL);
785 +  gint rc = pcre2_match(self->pcre, (PCRE2_SPTR) string, (PCRE2_SIZE) string_len, 0, 0, match_data, NULL);
786 +  pcre2_match_data_free(match_data);
787 +
788 +  if (rc == PCRE2_ERROR_NOMATCH)
789      {
790        return FALSE;
791      }
792 @@ -468,9 +472,7 @@
793    if (self->glob)
794      g_pattern_spec_free(self->glob);
795    if (self->pcre)
796 -    pcre_free(self->pcre);
797 -  if (self->pcre_extra)
798 -    pcre_free_study(self->pcre_extra);
799 +    pcre2_code_free(self->pcre);
800    g_free(self);
801  }
802  
803 diff -ur syslog-ng-syslog-ng-4.2.0.orig/modules/basicfuncs/tests/test_basicfuncs.c syslog-ng-syslog-ng-4.2.0/modules/basicfuncs/tests/test_basicfuncs.c
804 --- syslog-ng-syslog-ng-4.2.0.orig/modules/basicfuncs/tests/test_basicfuncs.c   2023-05-10 16:55:07.000000000 +0200
805 +++ syslog-ng-syslog-ng-4.2.0/modules/basicfuncs/tests/test_basicfuncs.c        2023-07-19 02:12:21.377815546 +0200
806 @@ -663,3 +663,8 @@
807  {
808    assert_template_format(param->template, param->expected);
809  }
810 +
811 +Test(basicfuncs, test_performance)
812 +{
813 +  perftest_template("$(list-search --start-index 1 --mode pcre .az '\"foo,\",\"bar\",\"baz\"')");
814 +}
815 diff -ur syslog-ng-syslog-ng-4.2.0.orig/modules/correlation/group-lines.c syslog-ng-syslog-ng-4.2.0/modules/correlation/group-lines.c
816 --- syslog-ng-syslog-ng-4.2.0.orig/modules/correlation/group-lines.c    2023-05-10 16:55:07.000000000 +0200
817 +++ syslog-ng-syslog-ng-4.2.0/modules/correlation/group-lines.c 2023-07-19 02:12:21.377815546 +0200
818 @@ -28,7 +28,6 @@
819  #include "messages.h"
820  #include "grouping-parser.h"
821  
822 -#include <pcre.h>
823  #include <iv.h>
824  
825  typedef struct _GroupLinesContext
826 diff -ur syslog-ng-syslog-ng-4.2.0.orig/modules/correlation/radix.c syslog-ng-syslog-ng-4.2.0/modules/correlation/radix.c
827 --- syslog-ng-syslog-ng-4.2.0.orig/modules/correlation/radix.c  2023-05-10 16:55:07.000000000 +0200
828 +++ syslog-ng-syslog-ng-4.2.0/modules/correlation/radix.c       2023-07-19 02:12:21.377815546 +0200
829 @@ -22,13 +22,12 @@
830   */
831  
832  #include "radix.h"
833 +#include "compat/pcre.h"
834  
835  #include <string.h>
836  #include <stdlib.h>
837  #include <limits.h>
838  
839 -#include <pcre.h>
840 -
841  /**************************************************************
842   * Parsing nodes.
843   **************************************************************/
844 @@ -129,80 +128,80 @@
845  
846  typedef struct _RParserPCREState
847  {
848 -  pcre *re;
849 -  pcre_extra *extra;
850 +  pcre2_code *re;
851  } RParserPCREState;
852  
853  gboolean
854  r_parser_pcre(gchar *str, gint *len, const gchar *param, gpointer state, RParserMatch *match)
855  {
856    RParserPCREState *self = (RParserPCREState *) state;
857 +  gboolean result = FALSE;
858    gint rc;
859 -  gint num_matches;
860 -
861 -  if (pcre_fullinfo(self->re, self->extra, PCRE_INFO_CAPTURECOUNT, &num_matches) < 0)
862 -    g_assert_not_reached();
863 -  if (num_matches > LOGMSG_MAX_MATCHES)
864 -    num_matches = LOGMSG_MAX_MATCHES;
865  
866 -  gsize matches_size = 3 * (num_matches + 1);
867 -  gint *matches = g_alloca(matches_size * sizeof(gint));
868 +  pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(self->re, NULL);
869 +  rc = pcre2_match(self->re, (PCRE2_SPTR) str, (PCRE2_SIZE) strlen(str), 0, 0, match_data, NULL);
870  
871 -  rc = pcre_exec(self->re, self->extra, str, strlen(str), 0, 0, matches, matches_size);
872 -
873 -  if (rc == PCRE_ERROR_NOMATCH)
874 -    {
875 -      return FALSE;
876 -    }
877 +  if (rc == PCRE2_ERROR_NOMATCH)
878 +    goto exit;
879  
880    if (rc < 0)
881      {
882        msg_error("Error while matching regexp", evt_tag_int("error_code", rc));
883 -      return FALSE;
884 +      goto exit;
885      }
886  
887    if (rc == 0)
888      {
889        msg_error("Error while storing matching substrings");
890 -      return FALSE;
891 +      goto exit;
892      }
893  
894 +  PCRE2_SIZE *matches = pcre2_get_ovector_pointer(match_data);
895 +
896    *len = matches[1] - matches[0];
897 -  return TRUE;
898 +  result = TRUE;
899 +exit:
900 +  pcre2_match_data_free(match_data);
901 +  return result;
902  }
903  
904  gpointer
905  r_parser_pcre_compile_state(const gchar *expr)
906  {
907    RParserPCREState *self = g_new0(RParserPCREState, 1);
908 -  const gchar *errptr;
909 -  gint erroffset;
910 +  gsize erroffset;
911    gint rc;
912  
913 -  self->re = pcre_compile2(expr, PCRE_ANCHORED, &rc, &errptr, &erroffset, NULL);
914 +  self->re = pcre2_compile((PCRE2_SPTR)expr, PCRE2_ZERO_TERMINATED, PCRE2_ANCHORED, &rc, &erroffset, NULL);
915    if (!self->re)
916      {
917 +      PCRE2_UCHAR error_message[128];
918 +
919 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
920 +
921        msg_error("Error while compiling regular expression",
922                  evt_tag_str("regular_expression", expr),
923                  evt_tag_str("error_at", &expr[erroffset]),
924                  evt_tag_int("error_offset", erroffset),
925 -                evt_tag_str("error_message", errptr),
926 +                evt_tag_str("error_message", (gchar *) error_message),
927                  evt_tag_int("error_code", rc));
928        g_free(self);
929        return NULL;
930      }
931 -  self->extra = pcre_study(self->re, 0, &errptr);
932 -  if (errptr)
933 +
934 +  /* optimize regexp */
935 +  rc = pcre2_jit_compile(self->re, PCRE2_JIT_COMPLETE);
936 +  if (rc < 0)
937      {
938 -      msg_error("Error while optimizing regular expression",
939 -                evt_tag_str("regular_expression", expr),
940 -                evt_tag_str("error_message", errptr));
941 -      pcre_free(self->re);
942 -      if (self->extra)
943 -        pcre_free(self->extra);
944 -      g_free(self);
945 -      return NULL;
946 +      PCRE2_UCHAR error_message[128];
947 +
948 +      pcre2_get_error_message(rc, error_message, sizeof(error_message));
949 +      msg_warning("radix: Error while JIT compiling regular expression",
950 +                  evt_tag_str("regular_expression", expr),
951 +                  evt_tag_str("error_message", (gchar *) error_message),
952 +                  evt_tag_int("error_code", rc));
953      }
954 +
955    return (gpointer) self;
956  }
957  
958 @@ -212,9 +211,7 @@
959    RParserPCREState *self = (RParserPCREState *) s;
960  
961    if (self->re)
962 -    pcre_free(self->re);
963 -  if (self->extra)
964 -    pcre_free(self->extra);
965 +    pcre2_code_free(self->re);
966    g_free(self);
967  }
968  
969 diff -ur syslog-ng-syslog-ng-4.2.0.orig/packaging/debian/control syslog-ng-syslog-ng-4.2.0/packaging/debian/control
970 --- syslog-ng-syslog-ng-4.2.0.orig/packaging/debian/control     2023-05-10 16:55:07.000000000 +0200
971 +++ syslog-ng-syslog-ng-4.2.0/packaging/debian/control  2023-07-19 02:12:21.377815546 +0200
972 @@ -21,7 +21,7 @@
973                 libbson-dev,
974                 libjson-c-dev | libjson0-dev,
975                 libwrap0-dev,
976 -               libpcre3-dev,
977 +               libpcre2-dev,
978                 libcap-dev [linux-any],
979                 libsystemd-dev (>= 209) [linux-any],
980                 libhiredis-dev,
981 diff -ur syslog-ng-syslog-ng-4.2.0.orig/packaging/rhel/syslog-ng.spec syslog-ng-syslog-ng-4.2.0/packaging/rhel/syslog-ng.spec
982 --- syslog-ng-syslog-ng-4.2.0.orig/packaging/rhel/syslog-ng.spec        2023-05-10 16:55:07.000000000 +0200
983 +++ syslog-ng-syslog-ng-4.2.0/packaging/rhel/syslog-ng.spec     2023-07-19 02:12:21.378815560 +0200
984 @@ -60,7 +60,7 @@
985  BuildRequires: libdbi-devel
986  BuildRequires: libnet-devel
987  BuildRequires: openssl-devel
988 -BuildRequires: pcre-devel
989 +BuildRequires: pcre2-devel
990  BuildRequires: libuuid-devel
991  BuildRequires: libesmtp-devel
992  BuildRequires: libcurl-devel