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 ®ex_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() {}