This is an automated email from the ASF dual-hosted git repository.

bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new b96659d2d9 Updated SSLSNIConfig to use the Regex class (pcre2) (#12219)
b96659d2d9 is described below

commit b96659d2d93787cc6a76778dd906c6705d0c8fd4
Author: Bryan Call <[email protected]>
AuthorDate: Mon Jul 7 14:54:51 2025 -0700

    Updated SSLSNIConfig to use the Regex class (pcre2) (#12219)
---
 include/iocore/net/SSLSNIConfig.h | 19 ++----------------
 include/tsutil/Regex.h            |  4 ++++
 src/iocore/net/SSLSNIConfig.cc    | 42 ++++++++++-----------------------------
 src/tsutil/Regex.cc               | 34 ++++++++++++++++++++++++++-----
 4 files changed, 46 insertions(+), 53 deletions(-)

diff --git a/include/iocore/net/SSLSNIConfig.h 
b/include/iocore/net/SSLSNIConfig.h
index 609b4c9a5b..4e2612cad8 100644
--- a/include/iocore/net/SSLSNIConfig.h
+++ b/include/iocore/net/SSLSNIConfig.h
@@ -37,15 +37,8 @@
 #include <strings.h>
 #include <memory>
 
-#if __has_include("pcre/pcre.h")
-#include <pcre/pcre.h>
-#elif __has_include("pcre.h")
-#include <pcre.h>
-#else
-#error "Unable to locate PCRE heeader"
-#endif
-
 #include "tsutil/ts_ip.h"
+#include "tsutil/Regex.h"
 
 #include "iocore/eventsystem/ConfigProcessor.h"
 #include "iocore/net/SNIActionItem.h"
@@ -63,14 +56,6 @@ struct NextHopProperty {
 
 using ActionVector = std::vector<std::unique_ptr<ActionItem>>;
 
-struct PcreFreer {
-  void
-  operator()(void *p)
-  {
-    pcre_free(p);
-  }
-};
-
 struct NamedElement {
   NamedElement() {}
 
@@ -85,7 +70,7 @@ struct NamedElement {
 
   std::vector<ts::port_range_t> inbound_port_ranges;
 
-  std::unique_ptr<pcre, PcreFreer> match;
+  Regex match;
 
   uint32_t rank = 0; ///< order of the config. smaller is higher.
 };
diff --git a/include/tsutil/Regex.h b/include/tsutil/Regex.h
index 9852269e1c..d7b4f1c5d3 100644
--- a/include/tsutil/Regex.h
+++ b/include/tsutil/Regex.h
@@ -91,6 +91,7 @@ public:
   Regex()              = default;
   Regex(Regex const &) = delete; // No copying.
   Regex(Regex &&that) noexcept;
+  Regex &operator=(Regex &&other);
   ~Regex();
 
   /** Compile the @a pattern into a regular expression.
@@ -140,6 +141,9 @@ public:
   /// @return The number of capture groups in the compiled pattern.
   int get_capture_count();
 
+  /// @return Is the compiled pattern empty?
+  bool empty() const;
+
 private:
   /// @internal This effectively wraps a void* so that we can avoid requiring 
the pcre2.h include for the user of the Regex
   /// API (see Regex.cc).
diff --git a/src/iocore/net/SSLSNIConfig.cc b/src/iocore/net/SSLSNIConfig.cc
index bbac57eb6f..060f654774 100644
--- a/src/iocore/net/SSLSNIConfig.cc
+++ b/src/iocore/net/SSLSNIConfig.cc
@@ -42,15 +42,12 @@
 #include <netinet/in.h>
 #include <sstream>
 #include <utility>
-#include <pcre.h>
 #include <algorithm>
 #include <functional>
 #include <utility>
 
 namespace
 {
-constexpr int OVECSIZE{30};
-
 DbgCtl dbg_ctl_ssl{"ssl"};
 DbgCtl dbg_ctl_ssl_sni{"ssl_sni"};
 DbgCtl dbg_ctl_sni{"sni"};
@@ -101,10 +98,8 @@ NamedElement::set_glob_name(std::string name)
 void
 NamedElement::set_regex_name(const std::string &regex_name)
 {
-  const char *err_ptr;
-  int         err_offset = 0;
   if (!regex_name.empty()) {
-    match.reset(pcre_compile(regex_name.c_str(), PCRE_ANCHORED | 
PCRE_CASELESS, &err_ptr, &err_offset, nullptr));
+    match.compile(regex_name, REFlags::RE_ANCHORED | 
REFlags::RE_CASE_INSENSITIVE);
   }
 }
 
@@ -116,7 +111,7 @@ SNIConfigParams::get_property_config(const std::string 
&servername) const
 {
   const NextHopProperty *nps = nullptr;
   for (auto &&item : next_hop_list) {
-    if (pcre_exec(item.match.get(), nullptr, servername.c_str(), 
servername.length(), 0, 0, nullptr, 0) >= 0) {
+    if (item.match.exec(servername)) {
       // Found a match
       nps = &item.prop;
       break;
@@ -232,43 +227,28 @@ SNIConfigParams::get(std::string_view servername, 
in_port_t dest_incoming_port)
   }
 
   // Check for wildcard matches
-  int ovector[OVECSIZE];
+  RegexMatches matches;
 
   for (auto const &retval : sni_action_list) {
     if (element != nullptr && element->rank < retval.rank) {
       break;
     }
 
-    int length = servername.length();
-    if (retval.match == nullptr && length == 0) {
+    if (retval.match.empty() && servername.length() == 0) {
       return {&retval.actions, {}};
-    } else if (auto offset = pcre_exec(retval.match.get(), nullptr, 
servername.data(), length, 0, 0, ovector, OVECSIZE);
-               offset >= 0) {
+    } else if (retval.match.exec(servername, matches) >= 0) {
       if (!is_port_in_the_ranges(retval.inbound_port_ranges, 
dest_incoming_port)) {
         continue;
       }
-      if (offset == 1) {
-        // first pair identify the portion of the subject string matched by 
the entire pattern
-        if (ovector[0] == 0 && ovector[1] == length) {
-          // full match
-          return {&retval.actions, {}};
-        } else {
-          continue;
-        }
-      }
-      // If contains groups
-      if (offset == 0) {
-        // reset to max if too many.
-        offset = OVECSIZE / 3;
+      if (matches.size() == 1) {
+        // full match
+        return {&retval.actions, {}};
       }
 
       ActionItem::Context::CapturedGroupViewVec groups;
-      groups.reserve(offset);
-      for (int strnum = 1; strnum < offset; strnum++) {
-        const std::size_t start  = ovector[2 * strnum];
-        const std::size_t length = ovector[2 * strnum + 1] - start;
-
-        groups.emplace_back(servername.data() + start, length);
+      groups.reserve(matches.size());
+      for (int count = 1; count < matches.size(); count++) {
+        groups.emplace_back(matches[count]);
       }
       return {&retval.actions, {std::move(groups)}};
     }
diff --git a/src/tsutil/Regex.cc b/src/tsutil/Regex.cc
index d1410da32e..19095323a4 100644
--- a/src/tsutil/Regex.cc
+++ b/src/tsutil/Regex.cc
@@ -213,6 +213,21 @@ Regex::Regex(Regex &&that) noexcept
   _Code::set(that._code, nullptr);
 }
 
+//----------------------------------------------------------------------------
+Regex &
+Regex::operator=(Regex &&other)
+{
+  if (this != &other) {
+    auto ptr = _Code::get(_code);
+    if (ptr != nullptr) {
+      pcre2_code_free(ptr);
+    }
+    _code = other._code;
+    _Code::set(other._code, nullptr);
+  }
+  return *this;
+}
+
 //----------------------------------------------------------------------------
 Regex::~Regex()
 {
@@ -297,12 +312,14 @@ Regex::exec(std::string_view subject, RegexMatches 
&matches) const
 
   matches._size = count;
 
-  if (count < 0) {
-    return count;
-  }
-
-  if (count > 0) {
+  // match was successful
+  if (count >= 0) {
     matches._subject = subject;
+
+    // match but the output vector was too small, adjust the size of the 
matches
+    if (count == 0) {
+      matches._size = 
pcre2_get_ovector_count(RegexMatches::_MatchData::get(matches._match_data));
+    }
   }
 
   return count;
@@ -319,6 +336,13 @@ Regex::get_capture_count()
   return captures;
 }
 
+//----------------------------------------------------------------------------
+bool
+Regex::empty() const
+{
+  return _Code::get(_code) == nullptr;
+}
+
 //----------------------------------------------------------------------------
 DFA::~DFA() {}
 

Reply via email to