This is an automated email from the ASF dual-hosted git repository. cmcfarlen pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 84527aaae39662a21024d07aaed672fbfef6bb68 Author: Chris McFarlen <ch...@mcfarlen.us> AuthorDate: Fri Sep 5 10:32:30 2025 -0500 Fallback to malloc for larger regex buffers (#12465) * Fallback to malloc for larger regex buffers * assert on match fail, better description in free. (cherry picked from commit 9286caac06c21eab0fe8f674d061f33caed6847c) --- include/tsutil/Regex.h | 1 + src/tsutil/Regex.cc | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/tsutil/Regex.h b/include/tsutil/Regex.h index 9852269e1c..7daaf5c453 100644 --- a/include/tsutil/Regex.h +++ b/include/tsutil/Regex.h @@ -66,6 +66,7 @@ public: private: constexpr static uint32_t DEFAULT_MATCHES = 10; static void *malloc(size_t size, void *caller); + static void free(void *p, void *caller); std::string_view _subject; char _buffer[24 + 96 + 28 * DEFAULT_MATCHES]; // 24 bytes for the general context, 96 bytes overhead, 28 bytes per match. size_t _buffer_bytes_used = 0; diff --git a/src/tsutil/Regex.cc b/src/tsutil/Regex.cc index d1410da32e..26a1dcc87c 100644 --- a/src/tsutil/Regex.cc +++ b/src/tsutil/Regex.cc @@ -126,15 +126,10 @@ struct RegexMatches::_MatchData { //---------------------------------------------------------------------------- RegexMatches::RegexMatches(uint32_t size) { - pcre2_general_context *ctx = - pcre2_general_context_create(&RegexMatches::malloc, [](void *, void *) -> void {}, static_cast<void *>(this)); + pcre2_general_context *ctx = pcre2_general_context_create(&RegexMatches::malloc, &RegexMatches::free, static_cast<void *>(this)); pcre2_match_data *match_data = pcre2_match_data_create(size, ctx); - if (match_data == nullptr) { - // buffer was too small, allocate from heap - debug_assert_message(false, "RegexMatches data buffer too small, increase the buffer size in Regex.h"); - match_data = pcre2_match_data_create(size, RegexContext::get_instance()->get_general_context()); - } + debug_assert_message(match_data, "Failed to allocate pcre2 match data from custom context"); _MatchData::set(_match_data, match_data); } @@ -152,8 +147,23 @@ RegexMatches::malloc(size_t size, void *caller) return ptr; } - // return nullptr if buffer is too small - return nullptr; + return ::malloc(size); +} + +void +RegexMatches::free(void *p, void *caller) +{ + auto *matches = static_cast<RegexMatches *>(caller); + + // Call free for any p outside _buffer + // If the pcre2 context requests more data than fits in our builtin buffer, we will call malloc + // to fulfil that request. + // !his checks for any pointers outside of our buffer in order to free that memory up. + // + // nullptr is outside of our buffer, but its ok to call ::free with nullptr. + if (!(p >= matches->_buffer && p < matches->_buffer + sizeof(matches->_buffer))) { + ::free(p); + } } //----------------------------------------------------------------------------