From fa5c0252f2a9d888bdf7ae1db4013412b65b5ee8 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Fri, 2 May 2025 09:58:55 -0700 Subject: [PATCH 1/3] Updated SSLSNIConfig to use the Regex class (pcre2) --- include/iocore/net/SSLSNIConfig.h | 19 ++----------------- include/tsutil/Regex.h | 4 ++++ src/iocore/net/SSLSNIConfig.cc | 18 ++++++++---------- src/tsutil/Regex.cc | 22 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/include/iocore/net/SSLSNIConfig.h b/include/iocore/net/SSLSNIConfig.h index 609b4c9a5b1..4e2612cad8c 100644 --- a/include/iocore/net/SSLSNIConfig.h +++ b/include/iocore/net/SSLSNIConfig.h @@ -37,15 +37,8 @@ #include #include -#if __has_include("pcre/pcre.h") -#include -#elif __has_include("pcre.h") -#include -#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>; -struct PcreFreer { - void - operator()(void *p) - { - pcre_free(p); - } -}; - struct NamedElement { NamedElement() {} @@ -85,7 +70,7 @@ struct NamedElement { std::vector inbound_port_ranges; - std::unique_ptr 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 9852269e1cf..d7b4f1c5d38 100644 --- a/include/tsutil/Regex.h +++ b/include/tsutil/Regex.h @@ -91,6 +91,7 @@ class Regex 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 @@ class Regex /// @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 19b631e782c..25494b87e5d 100644 --- a/src/iocore/net/SSLSNIConfig.cc +++ b/src/iocore/net/SSLSNIConfig.cc @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -100,10 +99,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); } } @@ -115,7 +112,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; @@ -231,23 +228,24 @@ SNIConfigParams::get(std::string_view servername, in_port_t dest_incoming_port) } // Check for wildcard matches - int ovector[OVECSIZE]; + RegexMatches matches; + size_t *ovector = nullptr; 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) { + size_t length = servername.length(); + if (retval.match.empty() == true && 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 (auto offset = retval.match.exec(servername, matches); offset > 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 + ovector = matches.get_ovector_pointer(); if (ovector[0] == 0 && ovector[1] == length) { // full match return {&retval.actions, {}}; diff --git a/src/tsutil/Regex.cc b/src/tsutil/Regex.cc index d1410da32eb..3a8273703d7 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() { @@ -319,6 +334,13 @@ Regex::get_capture_count() return captures; } +//---------------------------------------------------------------------------- +bool +Regex::empty() const +{ + return _Code::get(_code) == nullptr; +} + //---------------------------------------------------------------------------- DFA::~DFA() {} From 08608a843dad653a31673587d6262b6334cc82d7 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Fri, 2 May 2025 12:29:26 -0700 Subject: [PATCH 2/3] Updates to use RegexMatches --- src/iocore/net/SSLSNIConfig.cc | 32 ++++++++------------------------ src/tsutil/Regex.cc | 12 +++++++----- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/iocore/net/SSLSNIConfig.cc b/src/iocore/net/SSLSNIConfig.cc index 25494b87e5d..2bd060dc18e 100644 --- a/src/iocore/net/SSLSNIConfig.cc +++ b/src/iocore/net/SSLSNIConfig.cc @@ -229,43 +229,27 @@ SNIConfigParams::get(std::string_view servername, in_port_t dest_incoming_port) // Check for wildcard matches RegexMatches matches; - size_t *ovector = nullptr; for (auto const &retval : sni_action_list) { if (element != nullptr && element->rank < retval.rank) { break; } - size_t length = servername.length(); - if (retval.match.empty() == true && length == 0) { + if (retval.match.empty() && servername.length() == 0) { return {&retval.actions, {}}; - } else if (auto offset = retval.match.exec(servername, matches); 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 - ovector = matches.get_ovector_pointer(); - 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 = 0; 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 3a8273703d7..19095323a4c 100644 --- a/src/tsutil/Regex.cc +++ b/src/tsutil/Regex.cc @@ -312,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; From cac2aea7734365603758159d680e145bdb5b20c3 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Fri, 2 May 2025 12:49:13 -0700 Subject: [PATCH 3/3] Fixed aa error and a warning --- src/iocore/net/SSLSNIConfig.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/iocore/net/SSLSNIConfig.cc b/src/iocore/net/SSLSNIConfig.cc index 2bd060dc18e..d43126aff6d 100644 --- a/src/iocore/net/SSLSNIConfig.cc +++ b/src/iocore/net/SSLSNIConfig.cc @@ -48,8 +48,6 @@ namespace { -constexpr int OVECSIZE{30}; - DbgCtl dbg_ctl_ssl{"ssl"}; DbgCtl dbg_ctl_ssl_sni{"ssl_sni"}; DbgCtl dbg_ctl_sni{"sni"}; @@ -248,7 +246,7 @@ SNIConfigParams::get(std::string_view servername, in_port_t dest_incoming_port) ActionItem::Context::CapturedGroupViewVec groups; groups.reserve(matches.size()); - for (int count = 0; count < matches.size(); count++) { + for (int count = 1; count < matches.size(); count++) { groups.emplace_back(matches[count]); } return {&retval.actions, {std::move(groups)}};