From: Oleksii Shumeiko -X (oshumeik - SOFTSERVE INC at Cisco) Date: Wed, 19 Nov 2025 11:59:30 +0000 (+0000) Subject: Pull request #5000: ips_options: make pcre match data thread specific X-Git-Tag: 3.10.0.0~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5d709e9ef9241e0f8f82ec402bf29c37c22b5b2;p=thirdparty%2Fsnort3.git Pull request #5000: ips_options: make pcre match data thread specific Merge in SNORT/snort3 from ~OSHUMEIK/snort3:pcre2_mt to master Squashed commit of the following: commit c526c6db25247c43cbaa9f176838d94f18944bee Author: vhorbato Date: Mon Nov 17 18:26:07 2025 +0200 ips_options: make pcre match data thread specific --- diff --git a/src/ips_options/ips_pcre.cc b/src/ips_options/ips_pcre.cc index 95d9507cd..eb775ae3a 100644 --- a/src/ips_options/ips_pcre.cc +++ b/src/ips_options/ips_pcre.cc @@ -24,6 +24,7 @@ #endif #include +#include #include "detection/ips_context.h" #include "framework/cursor.h" @@ -35,6 +36,8 @@ #include "log/log_stats.h" #include "log/messages.h" #include "main/snort_config.h" +#include "main/thread.h" +#include "main/thread_config.h" #include "managers/ips_manager.h" #include "managers/module_manager.h" #include "profiler/profiler.h" @@ -59,15 +62,44 @@ void show_pcre_counts(); struct PcreData { - pcre2_code* re; /* compiled regex */ - pcre2_match_context* match_context; /* match_context */ - pcre2_match_data* match_data; /* match data space for storing results */ - int options; /* sp_pcre specific options (relative & inverse) */ + PcreData(); + ~PcreData(); + + pcre2_code* re; /* compiled regex */ + pcre2_match_context* match_context; /* match_context */ + std::vector match_data_store; /* match data space for storing results */ + int options; /* sp_pcre specific options (relative & inverse) */ char* expression; }; static THREAD_LOCAL ProfileStats pcrePerfStats; +PcreData::PcreData() : + re(nullptr), + match_context(nullptr), + match_data_store(ThreadConfig::get_instance_max(), nullptr), + options(0), + expression(nullptr) +{ } + +PcreData::~PcreData() +{ + if (expression) + snort_free(expression); + + assert(match_context); + pcre2_match_context_free(match_context); + + assert(re); + pcre2_code_free(re); + + for (auto* match_data : match_data_store) + { + assert(match_data); + pcre2_match_data_free(match_data); + } +} + struct PcreCounts { unsigned pcre_rules; @@ -294,7 +326,8 @@ static void pcre_parse(const SnortConfig* sc, const char* data, PcreData* pcre_d return; } - pcre_data->match_data = pcre2_match_data_create_from_pattern(pcre_data->re, nullptr); + for (auto& match_data : pcre_data->match_data_store) + match_data = pcre2_match_data_create_from_pattern(pcre_data->re, nullptr); /* now study it... */ if (USE_JIT) @@ -347,13 +380,18 @@ static bool pcre_search( found_offset = -1; + assert(get_instance_id() < pcre_data->match_data_store.size()); + + auto match_data = pcre_data->match_data_store[get_instance_id()]; + assert(match_data); + int result = pcre2_match( pcre_data->re, /* result of pcre_compile() */ (PCRE2_SPTR)buf, /* the subject string */ (PCRE2_SIZE)len, /* the length of the subject string */ (PCRE2_SIZE)start_offset, /* start at offset 0 in the subject */ 0, /* options (handled at compile time) */ - pcre_data->match_data, /* match data to store the match results */ + match_data, /* match data to store the match results */ pcre_data->match_context); /* match context for limits */ if (result >= 0) @@ -379,7 +417,7 @@ static bool pcre_search( * and a single int for scratch space. */ - ovector = pcre2_get_ovector_pointer(pcre_data->match_data); + ovector = pcre2_get_ovector_pointer(match_data); found_offset = ovector[1]; } else if (result == PCRE2_ERROR_NOMATCH) @@ -448,17 +486,7 @@ private: PcreOption::~PcreOption() { - if ( !config ) - return; - - if ( config->expression ) - snort_free(config->expression); - - pcre2_match_context_free(config->match_context); - pcre2_code_free(config->re); - pcre2_match_data_free(config->match_data); - - snort_free(config); + delete config; } uint32_t PcreOption::hash() const @@ -684,7 +712,7 @@ bool PcreModule::end(const char* name, int v, SnortConfig* sc) if ( !mod_regex ) { - data = (PcreData*)snort_calloc(sizeof(*data)); + data = new PcreData(); pcre_parse(sc, re.c_str(), data); }