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
 }

Reply via email to