Refactor build system to use libpcre2 as the default

Updated the build system and related source files to use libpcre2 as the
default regex library instead of the deprecated libpcre. This change
ensures future compatibility and aligns with the library's maintenance status.

To build with the old libpcre, the `--with-pcre` configuration parameter
can be specified.
This commit is contained in:
Gabor Berkes 2024-12-10 10:16:14 +00:00
parent 4fb22466a0
commit c6433df7b2
8 changed files with 51 additions and 54 deletions

View File

@ -26,7 +26,7 @@ jobs:
- {label: "wo geoip", opt: "--without-geoip" } - {label: "wo geoip", opt: "--without-geoip" }
- {label: "wo ssdeep", opt: "--without-ssdeep" } - {label: "wo ssdeep", opt: "--without-ssdeep" }
- {label: "with lmdb", opt: "--with-lmdb" } - {label: "with lmdb", opt: "--with-lmdb" }
- {label: "with pcre2", opt: "--with-pcre2" } - {label: "with pcre", opt: "--with-pcre" }
exclude: exclude:
- platform: {label: "x32"} - platform: {label: "x32"}
configure: {label: "wo geoip"} configure: {label: "wo geoip"}
@ -88,7 +88,7 @@ jobs:
- {label: "wo geoip", opt: "--without-geoip" } - {label: "wo geoip", opt: "--without-geoip" }
- {label: "wo ssdeep", opt: "--without-ssdeep" } - {label: "wo ssdeep", opt: "--without-ssdeep" }
- {label: "with lmdb", opt: "--with-lmdb" } - {label: "with lmdb", opt: "--with-lmdb" }
- {label: "with pcre2", opt: "--with-pcre2" } - {label: "with pcre", opt: "--with-pcre" }
steps: steps:
- name: Setup Dependencies - name: Setup Dependencies
# curl, pcre2 not installed because they're already # curl, pcre2 not installed because they're already

View File

@ -21,8 +21,8 @@ AC_ARG_WITH(
[test_paths="${with_pcre}"], [test_paths="${with_pcre}"],
[test_paths="/usr/local/libpcre /usr/local/pcre /usr/local /opt/libpcre /opt/pcre /opt /usr /opt/local"]) [test_paths="/usr/local/libpcre /usr/local/pcre /usr/local /opt/libpcre /opt/pcre /opt /usr /opt/local"])
if test "x${with_pcre2}" != "x" && test "x${with_pcre2}" != "xno"; then if test "x${with_pcre}" == "x" && test "x${with_pcre}" != "xno"; then
AC_MSG_NOTICE([pcre2 specified; omitting check for pcre]) AC_MSG_NOTICE([Support for pcre not requested; omitting check for pcre])
else else
AC_MSG_CHECKING([for libpcre config script]) AC_MSG_CHECKING([for libpcre config script])
@ -106,6 +106,7 @@ else
LIBS=$save_LIBS LIBS=$save_LIBS
fi fi
PCRE_CFLAGS="-DWITH_PCRE$ {PCRE_CFLAGS}"
AC_SUBST(PCRE_CONFIG) AC_SUBST(PCRE_CONFIG)
AC_SUBST(PCRE_VERSION) AC_SUBST(PCRE_VERSION)
AC_SUBST(PCRE_CPPFLAGS) AC_SUBST(PCRE_CPPFLAGS)

View File

@ -91,21 +91,16 @@ if test -z "${PCRE2_LDADD}"; then
PCRE2_FOUND=-1 PCRE2_FOUND=-1
fi fi
else else
if test -z "${PCRE2_MANDATORY}"; then PCRE2_FOUND=1
PCRE2_FOUND=2 AC_MSG_NOTICE([using PCRE2 v${PCRE2_VERSION}])
AC_MSG_NOTICE([PCRE2 is disabled by default.]) PCRE2_CFLAGS="${PCRE2_CFLAGS}"
else PCRE2_DISPLAY="${PCRE2_LDADD}, ${PCRE2_CFLAGS}"
PCRE2_FOUND=1 AC_SUBST(PCRE2_VERSION)
AC_MSG_NOTICE([using PCRE2 v${PCRE2_VERSION}]) AC_SUBST(PCRE2_LDADD)
PCRE2_CFLAGS="-DWITH_PCRE2 ${PCRE2_CFLAGS}" AC_SUBST(PCRE2_LIBS)
PCRE2_DISPLAY="${PCRE2_LDADD}, ${PCRE2_CFLAGS}" AC_SUBST(PCRE2_LDFLAGS)
AC_SUBST(PCRE2_VERSION) AC_SUBST(PCRE2_CFLAGS)
AC_SUBST(PCRE2_LDADD) AC_SUBST(PCRE2_DISPLAY)
AC_SUBST(PCRE2_LIBS)
AC_SUBST(PCRE2_LDFLAGS)
AC_SUBST(PCRE2_CFLAGS)
AC_SUBST(PCRE2_DISPLAY)
fi
fi fi

View File

@ -141,15 +141,16 @@ CHECK_LIBXML2
# #
# Check for libpcre # Check for libpcre only if explicitly requested
# #
CHECK_PCRE if test "x${with_pcre}" != "x" && test "x${with_pcre}" != "xno"; then
CHECK_PCRE
else
# #
# Check for pcre2 # Check for pcre2
# #
PROG_PCRE2 PROG_PCRE2
fi
# Checks for header files. # Checks for header files.

View File

@ -21,7 +21,7 @@
#include "src/operators/operator.h" #include "src/operators/operator.h"
#ifndef WITH_PCRE2 #ifdef WITH_PCRE
#if PCRE_HAVE_JIT #if PCRE_HAVE_JIT
#define pcre_study_opt PCRE_STUDY_JIT_COMPILE #define pcre_study_opt PCRE_STUDY_JIT_COMPILE
#else #else
@ -34,7 +34,7 @@ namespace modsecurity {
namespace operators { namespace operators {
VerifyCC::~VerifyCC() { VerifyCC::~VerifyCC() {
#if WITH_PCRE2 #ifndef WITH_PCRE
pcre2_code_free(m_pc); pcre2_code_free(m_pc);
#else #else
if (m_pc != NULL) { if (m_pc != NULL) {
@ -94,7 +94,7 @@ int VerifyCC::luhnVerify(const char *ccnumber, int len) {
bool VerifyCC::init(const std::string &param2, std::string *error) { bool VerifyCC::init(const std::string &param2, std::string *error) {
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(m_param.c_str()); PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(m_param.c_str());
uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE); uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE);
int errornumber = 0; int errornumber = 0;
@ -136,7 +136,7 @@ bool VerifyCC::init(const std::string &param2, std::string *error) {
bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule, bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& i, RuleMessage &ruleMessage) { const std::string& i, RuleMessage &ruleMessage) {
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
PCRE2_SIZE offset = 0; PCRE2_SIZE offset = 0;
size_t target_length = i.length(); size_t target_length = i.length();
PCRE2_SPTR pcre2_i = reinterpret_cast<PCRE2_SPTR>(i.c_str()); PCRE2_SPTR pcre2_i = reinterpret_cast<PCRE2_SPTR>(i.c_str());
@ -192,7 +192,7 @@ bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
"\" at " + i + ". [offset " + "\" at " + i + ". [offset " +
std::to_string(offset) + "]"); std::to_string(offset) + "]");
} }
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre2_match_data_free(match_data); pcre2_match_data_free(match_data);
#endif #endif
return true; return true;
@ -200,7 +200,7 @@ bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
} }
} }
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre2_match_data_free(match_data); pcre2_match_data_free(match_data);
#endif #endif

View File

@ -16,7 +16,7 @@
#ifndef SRC_OPERATORS_VERIFY_CC_H_ #ifndef SRC_OPERATORS_VERIFY_CC_H_
#define SRC_OPERATORS_VERIFY_CC_H_ #define SRC_OPERATORS_VERIFY_CC_H_
#if WITH_PCRE2 #ifndef WITH_PCRE
#define PCRE2_CODE_UNIT_WIDTH 8 #define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h> #include <pcre2.h>
#else #else
@ -38,7 +38,7 @@ class VerifyCC : public Operator {
/** @ingroup ModSecurity_Operator */ /** @ingroup ModSecurity_Operator */
explicit VerifyCC(std::unique_ptr<RunTimeString> param) explicit VerifyCC(std::unique_ptr<RunTimeString> param)
: Operator("VerifyCC", std::move(param)), : Operator("VerifyCC", std::move(param)),
#if WITH_PCRE2 #ifndef WITH_PCRE
m_pc(NULL), m_pc(NULL),
m_pcje(PCRE2_ERROR_JIT_BADOPTION) { } m_pcje(PCRE2_ERROR_JIT_BADOPTION) { }
#else #else
@ -52,7 +52,7 @@ class VerifyCC : public Operator {
RuleMessage &ruleMessage) override; RuleMessage &ruleMessage) override;
bool init(const std::string &param, std::string *error) override; bool init(const std::string &param, std::string *error) override;
private: private:
#if WITH_PCRE2 #ifndef WITH_PCRE
pcre2_code *m_pc; pcre2_code *m_pc;
int m_pcje; int m_pcje;
#else #else

View File

@ -23,7 +23,7 @@
#include "src/utils/geo_lookup.h" #include "src/utils/geo_lookup.h"
#ifndef WITH_PCRE2 #ifdef WITH_PCRE
#if PCRE_HAVE_JIT #if PCRE_HAVE_JIT
// NOTE: Add PCRE_STUDY_EXTRA_NEEDED so studying always yields a pcre_extra strucure // NOTE: Add PCRE_STUDY_EXTRA_NEEDED so studying always yields a pcre_extra strucure
// and we can selectively override match limits using a copy of that structure at runtime. // and we can selectively override match limits using a copy of that structure at runtime.
@ -35,7 +35,7 @@
#endif #endif
#endif #endif
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
class Pcre2MatchContextPtr { class Pcre2MatchContextPtr {
public: public:
Pcre2MatchContextPtr() Pcre2MatchContextPtr()
@ -62,7 +62,7 @@ namespace Utils {
// Helper function to tell us if the current config indicates CRLF is a valid newline sequence // Helper function to tell us if the current config indicates CRLF is a valid newline sequence
bool crlfIsNewline() { bool crlfIsNewline() {
#if WITH_PCRE2 #ifndef WITH_PCRE
uint32_t newline = 0; uint32_t newline = 0;
pcre2_config(PCRE2_CONFIG_NEWLINE, &newline); pcre2_config(PCRE2_CONFIG_NEWLINE, &newline);
bool crlf_is_newline = bool crlf_is_newline =
@ -89,7 +89,7 @@ bool crlfIsNewline() {
Regex::Regex(const std::string& pattern_, bool ignoreCase) Regex::Regex(const std::string& pattern_, bool ignoreCase)
: pattern(pattern_.empty() ? ".*" : pattern_) { : pattern(pattern_.empty() ? ".*" : pattern_) {
#if WITH_PCRE2 #ifndef WITH_PCRE
PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(pattern.c_str()); PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(pattern.c_str());
uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE); uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE);
if (ignoreCase) { if (ignoreCase) {
@ -117,7 +117,7 @@ Regex::Regex(const std::string& pattern_, bool ignoreCase)
Regex::~Regex() { Regex::~Regex() {
#if WITH_PCRE2 #ifndef WITH_PCRE
pcre2_code_free(m_pc); pcre2_code_free(m_pc);
#else #else
if (m_pc != NULL) { if (m_pc != NULL) {
@ -139,7 +139,7 @@ Regex::~Regex() {
std::list<SMatch> Regex::searchAll(const std::string& s) const { std::list<SMatch> Regex::searchAll(const std::string& s) const {
std::list<SMatch> retList; std::list<SMatch> retList;
int rc = 0; int rc = 0;
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str()); PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str());
PCRE2_SIZE offset = 0; PCRE2_SIZE offset = 0;
@ -183,14 +183,14 @@ std::list<SMatch> Regex::searchAll(const std::string& s) const {
} }
} while (rc > 0); } while (rc > 0);
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre2_match_data_free(match_data); pcre2_match_data_free(match_data);
#endif #endif
return retList; return retList;
} }
RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit) const { RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit) const {
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
Pcre2MatchContextPtr match_context; Pcre2MatchContextPtr match_context;
if (match_limit > 0) { if (match_limit > 0) {
// TODO: What if setting the match limit fails? // TODO: What if setting the match limit fails?
@ -235,7 +235,7 @@ RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCaptur
captures.push_back(capture); captures.push_back(capture);
} }
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre2_match_data_free(match_data); pcre2_match_data_free(match_data);
#endif #endif
return to_regex_result(rc); return to_regex_result(rc);
@ -243,7 +243,7 @@ RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCaptur
RegexResult Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit) const { RegexResult Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit) const {
bool prev_match_zero_length = false; bool prev_match_zero_length = false;
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
Pcre2MatchContextPtr match_context; Pcre2MatchContextPtr match_context;
if (match_limit > 0) { if (match_limit > 0) {
// TODO: What if setting the match limit fails? // TODO: What if setting the match limit fails?
@ -337,14 +337,14 @@ RegexResult Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>
} }
} }
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre2_match_data_free(match_data); pcre2_match_data_free(match_data);
#endif #endif
return RegexResult::Ok; return RegexResult::Ok;
} }
int Regex::search(const std::string& s, SMatch *match) const { int Regex::search(const std::string& s, SMatch *match) const {
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str()); PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str());
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL); pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL);
int ret = 0; int ret = 0;
@ -371,14 +371,14 @@ int Regex::search(const std::string& s, SMatch *match) const {
0); 0);
} }
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre2_match_data_free(match_data); pcre2_match_data_free(match_data);
#endif #endif
return ret; return ret;
} }
int Regex::search(const std::string& s) const { int Regex::search(const std::string& s) const {
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str()); PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str());
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL); pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL);
int rc = 0; int rc = 0;
@ -405,7 +405,7 @@ int Regex::search(const std::string& s) const {
RegexResult Regex::to_regex_result(int pcre_exec_result) const { RegexResult Regex::to_regex_result(int pcre_exec_result) const {
if ( if (
pcre_exec_result > 0 || pcre_exec_result > 0 ||
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre_exec_result == PCRE2_ERROR_NOMATCH pcre_exec_result == PCRE2_ERROR_NOMATCH
#else #else
pcre_exec_result == PCRE_ERROR_NOMATCH pcre_exec_result == PCRE_ERROR_NOMATCH
@ -413,7 +413,7 @@ RegexResult Regex::to_regex_result(int pcre_exec_result) const {
) { ) {
return RegexResult::Ok; return RegexResult::Ok;
} else if( } else if(
#ifdef WITH_PCRE2 #ifndef WITH_PCRE
pcre_exec_result == PCRE2_ERROR_MATCHLIMIT pcre_exec_result == PCRE2_ERROR_MATCHLIMIT
#else #else
pcre_exec_result == PCRE_ERROR_MATCHLIMIT pcre_exec_result == PCRE_ERROR_MATCHLIMIT

View File

@ -12,7 +12,7 @@
* directly using the email address security@modsecurity.org. * directly using the email address security@modsecurity.org.
* *
*/ */
#if WITH_PCRE2 #ifndef WITH_PCRE
#define PCRE2_CODE_UNIT_WIDTH 8 #define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h> #include <pcre2.h>
#else #else
@ -91,7 +91,7 @@ class Regex {
private: private:
RegexResult to_regex_result(int pcre_exec_result) const; RegexResult to_regex_result(int pcre_exec_result) const;
#if WITH_PCRE2 #ifndef WITH_PCRE
pcre2_code *m_pc; pcre2_code *m_pc;
int m_pcje; int m_pcje;
#else #else