This is an automated email from the ASF dual-hosted git repository. cmcfarlen pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 05f79a0c3996d799e5e787b530294154f933dcf0 Author: Bryan Call <[email protected]> AuthorDate: Fri Apr 19 13:48:36 2024 -0700 Regex: fix memory leak if the match buffer is too small (#11244) (cherry picked from commit e20845453c88e42d8b5c9e6a1ba34c33fad2ed09) --- include/tsutil/Regex.h | 2 +- src/tsutil/Regex.cc | 20 +++++++++++++------- src/tsutil/unit_tests/test_Regex.cc | 10 ++++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/tsutil/Regex.h b/include/tsutil/Regex.h index 44e10d53b2..11e862c7bd 100644 --- a/include/tsutil/Regex.h +++ b/include/tsutil/Regex.h @@ -67,7 +67,7 @@ private: constexpr static uint32_t DEFAULT_MATCHES = 10; static void *malloc(size_t size, void *caller); std::string_view _subject; - char _buffer[24 + 96 + 16 * DEFAULT_MATCHES]; // 24 bytes for the general context, 96 bytes overhead, 16 bytes per match. + 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; int32_t _size = 0; diff --git a/src/tsutil/Regex.cc b/src/tsutil/Regex.cc index fb2cddbb2e..ca54e5833e 100644 --- a/src/tsutil/Regex.cc +++ b/src/tsutil/Regex.cc @@ -21,13 +21,13 @@ limitations under the License. */ -#include "tsutil/Regex.h" +#include <tsutil/Regex.h> +#include <tsutil/Assert.h> #define PCRE2_CODE_UNIT_WIDTH 8 #include <pcre2.h> #include <array> -#include <assert.h> #include <vector> #include <mutex> @@ -172,7 +172,14 @@ RegexMatches::RegexMatches(uint32_t size) pcre2_general_context *ctx = pcre2_general_context_create( &RegexMatches::malloc, [](void *, void *) -> void {}, static_cast<void *>(this)); - _MatchData::set(_match_data, pcre2_match_data_create(size, ctx)); + 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()); + } + + _MatchData::set(_match_data, match_data); } //---------------------------------------------------------------------------- @@ -188,9 +195,8 @@ RegexMatches::malloc(size_t size, void *caller) return ptr; } - // otherwise use system malloc if the buffer is too small - void *ptr = ::malloc(size); - return ptr; + // return nullptr if buffer is too small + return nullptr; } //---------------------------------------------------------------------------- @@ -381,7 +387,7 @@ DFA::build(const std::string_view pattern, unsigned flags) int32_t DFA::compile(std::string_view pattern, unsigned flags) { - assert(_patterns.empty()); + release_assert(_patterns.empty()); this->build(pattern, flags); return _patterns.size(); } diff --git a/src/tsutil/unit_tests/test_Regex.cc b/src/tsutil/unit_tests/test_Regex.cc index f17d2b17c8..5aeff61a48 100644 --- a/src/tsutil/unit_tests/test_Regex.cc +++ b/src/tsutil/unit_tests/test_Regex.cc @@ -179,4 +179,14 @@ TEST_CASE("Regex", "[libts][Regex]") REQUIRE(r.compile(R"(bar)") == true); REQUIRE(r.exec("bar") == true); } + +// test with matches set to 100, don't run the test in debug mode or the test will abort with a message to increase the buffer size +#ifndef DEBUG + { + Regex r; + RegexMatches matches(100); + REQUIRE(r.compile(R"(foo)") == true); + REQUIRE(r.exec("foo", matches) == 1); + } +#endif }
