diff --git a/CMakeLists.txt b/CMakeLists.txt index 994ff5e0..6ca505f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ if (NOT WITH_EMBEDDED_SRC) endif () # Find dependencies via Find modules -find_package(PCRE REQUIRED) +find_package(PCRE2 REQUIRED) find_package(MbedTLS REQUIRED) find_package(Sodium REQUIRED) find_package(Cares REQUIRED) diff --git a/README.md b/README.md index 5f140532..327a9592 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ In general, you need the following build dependencies: * pkg-config * libmbedtls * libsodium (>= 1.0.4) -* libpcre3 (old pcre library) +* libpcre2 * libev * libc-ares * asciidoc (for documentation only) @@ -225,7 +225,7 @@ For some of the distributions, you might install build dependencies like this: ```bash # Installation of basic build dependencies ## Debian / Ubuntu -sudo apt-get install --no-install-recommends build-essential cmake libpcre3-dev asciidoc xmlto libev-dev libc-ares-dev libmbedtls-dev libsodium-dev pkg-config +sudo apt-get install --no-install-recommends build-essential cmake libpcre2-dev asciidoc xmlto libev-dev libc-ares-dev libmbedtls-dev libsodium-dev pkg-config ## CentOS / Fedora / RHEL sudo yum install gcc cmake make asciidoc xmlto c-ares-devel libev-devel ## Arch diff --git a/cmake/FindPCRE.cmake b/cmake/FindPCRE.cmake deleted file mode 100644 index e3ff0d9b..00000000 --- a/cmake/FindPCRE.cmake +++ /dev/null @@ -1,60 +0,0 @@ -# FindPCRE.cmake - Find PCRE library -# -# Sets: -# PCRE_FOUND -# PCRE_INCLUDE_DIRS -# PCRE_LIBRARIES - -include(FindPkgConfig) - -if(PKG_CONFIG_FOUND) - pkg_check_modules(_PCRE QUIET libpcre) -endif() - -if(_PCRE_FOUND) - set(PCRE_INCLUDE_DIRS ${_PCRE_INCLUDE_DIRS}) - set(PCRE_LIBRARIES ${_PCRE_LIBRARIES}) - set(PCRE_FOUND TRUE) -else() - # Try pcre-config - find_program(PCRE_CONFIG pcre-config) - if(PCRE_CONFIG) - execute_process(COMMAND ${PCRE_CONFIG} --cflags - OUTPUT_VARIABLE PCRE_CFLAGS - OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND ${PCRE_CONFIG} --libs - OUTPUT_VARIABLE PCRE_LDFLAGS - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX REPLACE "-I" "" PCRE_INCLUDE_DIRS "${PCRE_CFLAGS}") - set(PCRE_LIBRARIES ${PCRE_LDFLAGS}) - set(PCRE_FOUND TRUE) - else() - # Manual search - find_path(PCRE_INCLUDE_DIR - NAMES pcre.h - PATHS /usr/include /usr/local/include) - if(NOT PCRE_INCLUDE_DIR) - find_path(PCRE_INCLUDE_DIR - NAMES pcre/pcre.h - PATHS /usr/include /usr/local/include) - endif() - - find_library(PCRE_LIBRARY - NAMES pcre - PATHS /usr/lib /usr/local/lib) - - if(PCRE_INCLUDE_DIR AND PCRE_LIBRARY) - set(PCRE_INCLUDE_DIRS ${PCRE_INCLUDE_DIR}) - set(PCRE_LIBRARIES ${PCRE_LIBRARY}) - set(PCRE_FOUND TRUE) - else() - set(PCRE_FOUND FALSE) - endif() - endif() -endif() - -if(PCRE_FOUND) - message(STATUS "Found PCRE: ${PCRE_LIBRARIES}") -else() - message(FATAL_ERROR "Could not find PCRE library. Install libpcre3-dev or equivalent.") -endif() diff --git a/cmake/FindPCRE2.cmake b/cmake/FindPCRE2.cmake new file mode 100644 index 00000000..a89e9354 --- /dev/null +++ b/cmake/FindPCRE2.cmake @@ -0,0 +1,63 @@ +# FindPCRE2.cmake - Find PCRE2 library (8-bit) +# +# Sets: +# PCRE2_FOUND +# PCRE2_INCLUDE_DIRS +# PCRE2_LIBRARIES + +include(FindPkgConfig) + +if(PKG_CONFIG_FOUND) + pkg_check_modules(_PCRE2 QUIET libpcre2-8) +endif() + +if(_PCRE2_FOUND) + set(PCRE2_INCLUDE_DIRS ${_PCRE2_INCLUDE_DIRS}) + set(PCRE2_LIBRARIES ${_PCRE2_LIBRARIES}) + set(PCRE2_FOUND TRUE) +else() + # Try pcre2-config + find_program(PCRE2_CONFIG pcre2-config) + if(PCRE2_CONFIG) + execute_process(COMMAND ${PCRE2_CONFIG} --cflags + OUTPUT_VARIABLE PCRE2_CFLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${PCRE2_CONFIG} --libs8 + OUTPUT_VARIABLE PCRE2_LDFLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX REPLACE "-I" "" PCRE2_INCLUDE_DIRS "${PCRE2_CFLAGS}") + set(PCRE2_LIBRARIES ${PCRE2_LDFLAGS}) + set(PCRE2_FOUND TRUE) + else() + # Manual search + find_path(PCRE2_INCLUDE_DIR + NAMES pcre2.h + HINTS + /opt/homebrew/include + /usr/local/include + /usr/include + ) + + find_library(PCRE2_LIBRARY + NAMES pcre2-8 + HINTS + /opt/homebrew/lib + /usr/local/lib + /usr/lib + ) + + if(PCRE2_INCLUDE_DIR AND PCRE2_LIBRARY) + set(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR}) + set(PCRE2_LIBRARIES ${PCRE2_LIBRARY}) + set(PCRE2_FOUND TRUE) + else() + set(PCRE2_FOUND FALSE) + endif() + endif() +endif() + +if(PCRE2_FOUND) + message(STATUS "Found PCRE2: ${PCRE2_LIBRARIES}") +else() + message(FATAL_ERROR "Could not find PCRE2 library. Install libpcre2-dev or equivalent.") +endif() diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake index 4c30cb18..82216519 100644 --- a/cmake/config.h.cmake +++ b/cmake/config.h.cmake @@ -87,11 +87,8 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NET_IF_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_PCRE_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_PCRE_PCRE_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PCRE2_H 1 /* Have PTHREAD_PRIO_INHERIT. */ #cmakedefine HAVE_PTHREAD_PRIO_INHERIT 1 diff --git a/cmake/configure.cmake b/cmake/configure.cmake index fd381f3a..2c2d915f 100644 --- a/cmake/configure.cmake +++ b/cmake/configure.cmake @@ -56,8 +56,10 @@ else () endif () check_include_files(linux/tcp.h HAVE_LINUX_TCP_H) check_include_files(net/if.h HAVE_NET_IF_H) -check_include_files(pcre.h HAVE_PCRE_H) -check_include_files(pcre/pcre.h HAVE_PCRE_PCRE_H) +set(CMAKE_REQUIRED_DEFINITIONS_SAVE ${CMAKE_REQUIRED_DEFINITIONS}) +set(CMAKE_REQUIRED_DEFINITIONS "-DPCRE2_CODE_UNIT_WIDTH=8") +check_include_files(pcre2.h HAVE_PCRE2_H) +set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS_SAVE}) check_symbol_exists(PTHREAD_PRIO_INHERIT pthread.h HAVE_PTHREAD_PRIO_INHERIT) check_function_exists(select HAVE_SELECT) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 31513c20..18ae7ba0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -92,7 +92,7 @@ set(SS_WERROR_FLAGS -Werror) # that may be in /opt/homebrew/include (e.g. mbedtls 4.x vs 3.x) include_directories(BEFORE ${MBEDTLS_INCLUDE_DIRS}) include_directories(${SODIUM_INCLUDE_DIRS}) -include_directories(${PCRE_INCLUDE_DIRS}) +include_directories(${PCRE2_INCLUDE_DIRS}) include_directories(${CARES_INCLUDE_DIRS}) # Extract mbedTLS lib dir to ensure static/shared libs come from same version @@ -106,7 +106,7 @@ find_library(LIBMBEDCRYPTO libmbedcrypto.a HINTS ${_MBEDTLS_LIB_DIR} NO_DEFAULT_ find_library(LIBMBEDCRYPTO libmbedcrypto.a) find_library(LIBEV libev.a) find_library(LIBUDNS libcares.a) -find_library(LIBPCRE libpcre.a) +find_library(LIBPCRE2 libpcre2-8.a) # Dependencies we need for static and shared list(APPEND DEPS @@ -114,7 +114,7 @@ list(APPEND DEPS bloom ${LIBEV} ${LIBUDNS} - ${LIBPCRE} + ${LIBPCRE2} ${LIBSODIUM} ${LIBMBEDTLS} ${LIBMBEDCRYPTO} @@ -122,7 +122,7 @@ list(APPEND DEPS if (MINGW) list(APPEND DEPS ws2_32 iphlpapi) -add_compile_definitions(CARES_STATICLIB PCRE_STATIC) +add_compile_definitions(CARES_STATICLIB PCRE2_STATIC) endif () endif () @@ -133,7 +133,7 @@ find_library(LIBMBEDCRYPTO_SHARED mbedcrypto HINTS ${_MBEDTLS_LIB_DIR} NO_DEFAUL find_library(LIBMBEDCRYPTO_SHARED mbedcrypto) find_library(LIBEV_SHARED ev) find_library(LIBUDNS_SHARED cares) -find_library(LIBPCRE_SHARED pcre) +find_library(LIBPCRE2_SHARED pcre2-8) if (WITH_EMBEDDED_SRC) list(APPEND DEPS_SHARED @@ -143,7 +143,7 @@ list(APPEND DEPS_SHARED ipset-shared ${LIBEV_SHARED} ${LIBUDNS_SHARED} - ${LIBPCRE_SHARED} + ${LIBPCRE2_SHARED} ${LIBSODIUM_SHARED} ${LIBMBEDTLS_SHARED} ${LIBMBEDCRYPTO_SHARED} @@ -159,7 +159,7 @@ list(APPEND DEPS_SHARED ${LIBCORKIPSET_SHARED} ${LIBEV_SHARED} ${LIBUDNS_SHARED} - ${LIBPCRE_SHARED} + ${LIBPCRE2_SHARED} ${LIBSODIUM_SHARED} ${LIBMBEDTLS_SHARED} ${LIBMBEDCRYPTO_SHARED} diff --git a/src/rule.c b/src/rule.c index 737013e6..6f8428de 100644 --- a/src/rule.c +++ b/src/rule.c @@ -78,16 +78,21 @@ int init_rule(rule_t *rule) { if (rule->pattern_re == NULL) { - const char *reerr; - int reerroffset; + int errcode; + PCRE2_SIZE erroffset; rule->pattern_re = - pcre_compile(rule->pattern, 0, &reerr, &reerroffset, NULL); + pcre2_compile((PCRE2_SPTR)rule->pattern, PCRE2_ZERO_TERMINATED, + 0, &errcode, &erroffset, NULL); if (rule->pattern_re == NULL) { + PCRE2_UCHAR errbuf[256]; + pcre2_get_error_message(errcode, errbuf, sizeof(errbuf)); LOGE("Regex compilation of \"%s\" failed: %s, offset %d", - rule->pattern, reerr, reerroffset); + rule->pattern, errbuf, (int)erroffset); return 0; } + rule->match_data = pcre2_match_data_create_from_pattern( + rule->pattern_re, NULL); } return 1; @@ -105,8 +110,8 @@ lookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len) cork_dllist_foreach_void(rules, curr, next) { rule_t *rule = cork_container_of(curr, rule_t, entries); - if (pcre_exec(rule->pattern_re, NULL, - name, name_len, 0, 0, NULL, 0) >= 0) + if (pcre2_match(rule->pattern_re, (PCRE2_SPTR)name, + name_len, 0, 0, rule->match_data, NULL) >= 0) return rule; } @@ -127,7 +132,9 @@ free_rule(rule_t *rule) return; ss_free(rule->pattern); + if (rule->match_data != NULL) + pcre2_match_data_free(rule->match_data); if (rule->pattern_re != NULL) - pcre_free(rule->pattern_re); + pcre2_code_free(rule->pattern_re); ss_free(rule); } diff --git a/src/rule.h b/src/rule.h index 015bc42b..ae907f77 100644 --- a/src/rule.h +++ b/src/rule.h @@ -33,17 +33,15 @@ #include -#ifdef HAVE_PCRE_H -#include -#elif HAVE_PCRE_PCRE_H -#include -#endif +#define PCRE2_CODE_UNIT_WIDTH 8 +#include typedef struct rule { char *pattern; /* Runtime fields */ - pcre *pattern_re; + pcre2_code *pattern_re; + pcre2_match_data *match_data; struct cork_dllist_item entries; } rule_t; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e8490bdc..9a342613 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,7 +3,7 @@ include_directories(BEFORE ${MBEDTLS_INCLUDE_DIRS}) include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_BINARY_DIR}/src) include_directories(${SODIUM_INCLUDE_DIRS}) -include_directories(${PCRE_INCLUDE_DIRS}) +include_directories(${PCRE2_INCLUDE_DIRS}) include_directories(${CARES_INCLUDE_DIRS}) if(WITH_EMBEDDED_SRC) @@ -69,7 +69,7 @@ ss_add_test(test_ppbloom # test_rule - needs pcre and cork set(TEST_RULE_LIBS - ${LIBPCRE_SHARED} + ${LIBPCRE2_SHARED} ${LIBSODIUM_SHARED} ) if(WITH_EMBEDDED_SRC) diff --git a/tests/test_rule.c b/tests/test_rule.c index 235965f0..8c14b27a 100644 --- a/tests/test_rule.c +++ b/tests/test_rule.c @@ -52,8 +52,10 @@ test_init_rule(void) (void)ret; assert(rule->pattern_re != NULL); + if (rule->match_data) + pcre2_match_data_free(rule->match_data); if (rule->pattern_re) - pcre_free(rule->pattern_re); + pcre2_code_free(rule->pattern_re); free(rule->pattern); free(rule); } @@ -102,10 +104,12 @@ test_lookup_rule(void) (void)found; /* Clean up */ - if (rule1->pattern_re) pcre_free(rule1->pattern_re); + if (rule1->match_data) pcre2_match_data_free(rule1->match_data); + if (rule1->pattern_re) pcre2_code_free(rule1->pattern_re); free(rule1->pattern); free(rule1); - if (rule2->pattern_re) pcre_free(rule2->pattern_re); + if (rule2->match_data) pcre2_match_data_free(rule2->match_data); + if (rule2->pattern_re) pcre2_code_free(rule2->pattern_re); free(rule2->pattern); free(rule2); }