Control: tags -1 + patch Please find attached a patch, build-tested only.
Description: Port to PCRE2. Bug-Debian: https://bugs.debian.org/999968 Author: Yavor Doganov <ya...@gnu.org> Forwarded: no Last-Update: 2023-12-17 ---
--- sagan-1.2.0.orig/configure.ac +++ sagan-1.2.0/configure.ac @@ -392,14 +392,25 @@ CPPFLAGS="${CPPFLAGS} -I${with_libpcre_includes}" fi -AC_CHECK_HEADER(pcre.h,,[AC_ERROR(pcre.h not found ...)]) +AC_CHECK_HEADER([pcre2.h], [], [AC_MSG_ERROR([pcre2.h not found ...])], +[[#define PCRE2_CODE_UNIT_WIDTH 8 +]]) if test "$with_libpcre_libraries" != "no"; then LDFLAGS="${LDFLAGS} -L${with_libpcre_libraries}" fi PCRE="" -AC_CHECK_LIB(pcre, pcre_get_substring,, PCRE="no") +LIBS="$LIBS -lpcre2-8" +AC_MSG_CHECKING([for pcre library]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> +]], +[[pcre2_match_data *md = pcre2_match_data_create(4, NULL);]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + PCRE="no"]) if test "$PCRE" = "no"; then echo echo " ERROR! pcre library not found, go get it" @@ -408,98 +419,44 @@ exit 1 fi -# libpcre 8.35 (especially on debian) has a known issue that results in segfaults -if test "$with_libpcre_libraries" = "no"; then - PKG_CHECK_MODULES(LIBPCREVERSION, [libpcre = 8.35],[libpcre_buggy_found="yes"],[libprce_buggy_found="no"]) - if test "$libpcre_buggy_found" = "yes"; then - echo - echo " Warning! vulnerable libpcre version 8.35 found" - echo " This version has a known issue that could result in segfaults" - echo " please upgrade to a newer version of pcre which you can get from" - echo " www.pcre.org. For more information, see issue #1693" - echo - echo " Continuing for now with JIT disabled..." - echo - fi -fi - -# To prevent duping the lib link we reset LIBS after this check. Setting action-if-found to NULL doesn't seem to work -# see: http://blog.flameeyes.eu/2008/04/29/i-consider-ac_check_lib-harmful -PCRE="" -TMPLIBS="${LIBS}" -AC_CHECK_LIB(pcre, pcre_dfa_exec,, PCRE="no") -if test "$PCRE" = "no"; then - echo - echo " ERROR! pcre library was found but version was < 6.0" - echo " please upgrade to a newer version of pcre which you can get from" - echo " www.pcre.org." - echo - exit 1 -fi -LIBS="${TMPLIBS}" - -AC_TRY_COMPILE([ #include <pcre.h> ], - [ int eo = 0; eo |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; ], - [ pcre_match_limit_recursion_available=yes ], [:] -) - -if test "$pcre_match_limit_recursion_available" != "yes"; then - echo - echo " Warning! pcre extra opt PCRE_EXTRA_MATCH_LIMIT_RECURSION not found" - echo " This could lead to potential DoS please upgrade to pcre >= 6.5" - echo " from www.pcre.org." - echo " Continuing for now...." - echo - AC_DEFINE([NO_PCRE_MATCH_RLIMIT],[1],[Pcre PCRE_EXTRA_MATCH_LIMIT_RECURSION not available]) -fi - -TMPCFLAGS="${CFLAGS}" -CFLAGS="-O0 -g -Werror -Wall" -AC_TRY_COMPILE([ #include <pcre.h> ], - [ pcre_extra *extra = NULL; pcre_free_study(extra); ], - [ AC_DEFINE([HAVE_PCRE_FREE_STUDY], [1], [Pcre pcre_free_study supported])], [:] -) -CFLAGS="${TMPCFLAGS}" - - #enable support for PCRE-jit available since pcre-8.20 AC_MSG_CHECKING(for PCRE JIT support) -AC_TRY_COMPILE([ #include <pcre.h> ], - [ - int jit = 0; - pcre_config(PCRE_CONFIG_JIT, &jit); - ], +AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> +]], +[[uint32_t jit = 0; + pcre2_config(PCRE2_CONFIG_JIT, &jit); + if (jit) + exit(EXIT_SUCCESS); + exit(EXIT_FAILURE);]])], [ pcre_jit_available=yes ], [ pcre_jit_available=no ] ) -# bug 1693, libpcre 8.35 is broken and debian jessie is still using that -if test "$libpcre_buggy_found" = "yes"; then - pcre_jit_available="no, libpcre 8.35 blacklisted" -fi - if test "x$pcre_jit_available" = "xyes"; then AC_MSG_RESULT(yes) AC_DEFINE([PCRE_HAVE_JIT], [1], [Pcre with JIT compiler support enabled]) AC_MSG_CHECKING(for PCRE JIT support usability) - AC_TRY_COMPILE([ #include <pcre.h> ], - [ - const char* regexstr = "(a|b|c|d)"; - pcre *re; - const char *error; - pcre_extra *extra; - int err_offset; - re = pcre_compile(regexstr,0, &error, &err_offset,NULL); - extra = pcre_study(re, PCRE_STUDY_JIT_COMPILE, &error); - if (extra == NULL) - exit(EXIT_FAILURE); - int jit = 0; - int ret = pcre_fullinfo(re, extra, PCRE_INFO_JIT, &jit); - if (ret != 0 || jit != 1) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> +]], + [[ + PCRE2_SPTR regexstr = "(a|b|c|d)"; + pcre2_code *re; + int error; + PCRE2_SIZE err_offset; + re = pcre2_compile(regexstr, PCRE2_ZERO_TERMINATED, 0, + &error, &err_offset, NULL); + pcre2_jit_compile(re, PCRE2_JIT_COMPLETE); + size_t jit = 0; + int ret = pcre2_pattern_info(re, PCRE2_INFO_JITSIZE, &jit); + if (ret != 0 || jit == 0) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); - ], + ]])], [ pcre_jit_works=yes ], [:] ) if test "x$pcre_jit_works" != "xyes"; then --- sagan-1.2.0.orig/src/processors/engine.c +++ sagan-1.2.0/src/processors/engine.c @@ -131,7 +131,7 @@ int sagan_match = 0; /* Used to determine if all has "matched" (content, pcre, meta_content, etc) */ int rc = 0; - int ovector[PCRE_OVECCOUNT]; + pcre2_match_data *ovector; int alter_num = 0; int meta_alter_num = 0; @@ -221,6 +221,8 @@ /* Search for matches */ + ovector = pcre2_match_data_create(PCRE_OVECCOUNT, NULL); + /* First we search for 'program' and such. This way, we don't waste CPU * time with pcre/content. */ @@ -460,7 +462,7 @@ for(z=0; z<rulestruct[b].pcre_count; z++) { - rc = pcre_exec( rulestruct[b].re_pcre[z], rulestruct[b].pcre_extra[z], SaganProcSyslog_LOCAL->syslog_message, (int)strlen(SaganProcSyslog_LOCAL->syslog_message), 0, 0, ovector, PCRE_OVECCOUNT); + rc = pcre2_match( rulestruct[b].re_pcre[z], (PCRE2_SPTR)SaganProcSyslog_LOCAL->syslog_message, strlen(SaganProcSyslog_LOCAL->syslog_message), 0, 0, ovector, NULL); if ( rc > 0 ) { @@ -1425,6 +1427,7 @@ free(processor_info_engine); free(lookup_cache); + pcre2_match_data_free(ovector); #ifdef HAVE_LIBLOGNORM if ( json_normalize != NULL ) --- sagan-1.2.0.orig/src/rules.c +++ sagan-1.2.0/src/rules.c @@ -41,7 +41,8 @@ #include <string.h> #include <getopt.h> #include <time.h> -#include <pcre.h> +#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> #include "version.h" @@ -98,8 +99,8 @@ sbool found = 0; sbool bad_rule = 0; - const char *error; - int erroffset; + int error; + PCRE2_SIZE erroffset; FILE *rulesfile; char ruleset_fullname[MAXPATH]; @@ -174,7 +175,7 @@ int port_2_count=0; sbool pcreflag=0; - int pcreoptions=0; + uint32_t pcreoptions=0; int i=0; int d; @@ -2091,25 +2092,25 @@ { case 'i': - if ( pcreflag == 1 ) pcreoptions |= PCRE_CASELESS; + if ( pcreflag == 1 ) pcreoptions |= PCRE2_CASELESS; break; case 's': - if ( pcreflag == 1 ) pcreoptions |= PCRE_DOTALL; + if ( pcreflag == 1 ) pcreoptions |= PCRE2_DOTALL; break; case 'm': - if ( pcreflag == 1 ) pcreoptions |= PCRE_MULTILINE; + if ( pcreflag == 1 ) pcreoptions |= PCRE2_MULTILINE; break; case 'x': - if ( pcreflag == 1 ) pcreoptions |= PCRE_EXTENDED; + if ( pcreflag == 1 ) pcreoptions |= PCRE2_EXTENDED; break; case 'A': - if ( pcreflag == 1 ) pcreoptions |= PCRE_ANCHORED; + if ( pcreflag == 1 ) pcreoptions |= PCRE2_ANCHORED; break; case 'E': - if ( pcreflag == 1 ) pcreoptions |= PCRE_DOLLAR_ENDONLY; + if ( pcreflag == 1 ) pcreoptions |= PCRE2_DOLLAR_ENDONLY; break; case 'G': - if ( pcreflag == 1 ) pcreoptions |= PCRE_UNGREEDY; + if ( pcreflag == 1 ) pcreoptions |= PCRE2_UNGREEDY; break; @@ -2147,28 +2148,20 @@ /* We store the compiled/study results. This saves us some CPU time during searching - Champ Clark III - 02/01/2011 */ - rulestruct[counters->rulecount].re_pcre[pcre_count] = pcre_compile( pcrerule, pcreoptions, &error, &erroffset, NULL ); + rulestruct[counters->rulecount].re_pcre[pcre_count] = pcre2_compile( (PCRE2_SPTR)pcrerule, strlen(pcrerule), pcreoptions, &error, &erroffset, NULL ); #ifdef PCRE_HAVE_JIT if ( config->pcre_jit == 1 ) { - pcreoptions |= PCRE_STUDY_JIT_COMPILE; - } -#endif + pcre2_jit_compile(rulestruct[counters->rulecount].re_pcre[pcre_count], PCRE2_JIT_COMPLETE); - rulestruct[counters->rulecount].pcre_extra[pcre_count] = pcre_study( rulestruct[counters->rulecount].re_pcre[pcre_count], pcreoptions, &error); - -#ifdef PCRE_HAVE_JIT - - if ( config->pcre_jit == 1 ) - { - int jit = 0; + size_t jit = 0; rc = 0; - rc = pcre_fullinfo(rulestruct[counters->rulecount].re_pcre[pcre_count], rulestruct[counters->rulecount].pcre_extra[pcre_count], PCRE_INFO_JIT, &jit); + rc = pcre2_pattern_info(rulestruct[counters->rulecount].re_pcre[pcre_count], PCRE2_INFO_JITSIZE, &jit); - if (rc != 0 || jit != 1) + if (rc != 0 || jit == 0) { Sagan_Log(WARN, "[%s, line %d] PCRE JIT does not support regexp in %s at line %d (pcre: \"%s\"). Continuing without PCRE JIT enabled for this rule.", __FILE__, __LINE__, ruleset_fullname, linecount, pcrerule); } --- sagan-1.2.0.orig/src/rules.h +++ sagan-1.2.0/src/rules.h @@ -79,8 +79,7 @@ unsigned s_size_rule; char s_msg[MAX_SAGAN_MSG]; - pcre *re_pcre[MAX_PCRE]; - pcre_extra *pcre_extra[MAX_PCRE]; + pcre2_code *re_pcre[MAX_PCRE]; char s_content[MAX_CONTENT][256]; char s_reference[MAX_REFERENCE][256]; --- sagan-1.2.0.orig/src/sagan.c +++ sagan-1.2.0/src/sagan.c @@ -42,7 +42,8 @@ #include <getopt.h> #include <time.h> #include <signal.h> -#include <pcre.h> +#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> #include <limits.h> #include <stdint.h> #include <inttypes.h> @@ -224,6 +225,7 @@ char *psyslogstring = NULL; char syslogstring[MAX_SYSLOGMSG]; + char pcrever[24]; signed char c; int rc=0; @@ -894,7 +896,8 @@ Sagan_Log(NORMAL, " \\/)\"(\\/ Version %s", VERSION); Sagan_Log(NORMAL, " (_o_) Champ Clark III & The Quadrant InfoSec Team [quadrantsec.com]"); Sagan_Log(NORMAL, " / \\/) Copyright (C) 2009-2018 Quadrant Information Security, et al."); - Sagan_Log(NORMAL, " (|| ||) Using PCRE version: %s", pcre_version()); + pcre2_config(PCRE2_CONFIG_VERSION, pcrever); + Sagan_Log(NORMAL, " (|| ||) Using PCRE version: %s", pcrever); Sagan_Log(NORMAL, " oo-oo Sagan is processing events....."); Sagan_Log(NORMAL, ""); --- sagan-1.2.0.orig/src/sagan.h +++ sagan-1.2.0/src/sagan.h @@ -32,7 +32,8 @@ #include <stdio.h> #include <stdint.h> #include <stddef.h> -#include <pcre.h> +#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> #include <time.h> #include <arpa/inet.h>