Migrate from PCRE to PCRE2

Replace legacy PCRE (libpcre3) with PCRE2 (libpcre2-8). PCRE1 has been
end-of-life since 2021.

- src/rule.h: use pcre2_code and pcre2_match_data types
- src/rule.c: pcre_compile -> pcre2_compile, pcre_exec -> pcre2_match,
  pcre_free -> pcre2_code_free, with proper error message retrieval
- cmake/FindPCRE.cmake -> cmake/FindPCRE2.cmake: find libpcre2-8 via
  pkg-config, pcre2-config, or manual search
- Update all CMakeLists.txt, config.h.cmake, configure.cmake, README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Max Lv
2026-02-07 16:40:27 +08:00
committed by Max Lv
co-authored by Claude Opus 4.6
parent 1c404eccf4
commit e36d03b5f6
11 changed files with 106 additions and 95 deletions
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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
-60
View File
@@ -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()
+63
View File
@@ -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()
+2 -5
View File
@@ -87,11 +87,8 @@
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1
/* Define to 1 if you have the <pcre.h> header file. */
#cmakedefine HAVE_PCRE_H 1
/* Define to 1 if you have the <pcre/pcre.h> header file. */
#cmakedefine HAVE_PCRE_PCRE_H 1
/* Define to 1 if you have the <pcre2.h> header file. */
#cmakedefine HAVE_PCRE2_H 1
/* Have PTHREAD_PRIO_INHERIT. */
#cmakedefine HAVE_PTHREAD_PRIO_INHERIT 1
+4 -2
View File
@@ -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)
+7 -7
View File
@@ -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}
+14 -7
View File
@@ -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);
}
+4 -6
View File
@@ -33,17 +33,15 @@
#include <libcork/ds.h>
#ifdef HAVE_PCRE_H
#include <pcre.h>
#elif HAVE_PCRE_PCRE_H
#include <pcre/pcre.h>
#endif
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
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;
+2 -2
View File
@@ -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)
+7 -3
View File
@@ -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);
}