diff --git a/src/Makefile.am b/src/Makefile.am index e69c9ee4..2dbed799 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -247,7 +247,8 @@ UTILS = \ REGEX = \ regex/regex.cc \ - regex/backend/pcre.cc + regex/backend/pcre.cc \ + regex/backend/re2.cc COLLECTION = \ diff --git a/src/regex/backend/re2.cc b/src/regex/backend/re2.cc new file mode 100644 index 00000000..d1f2abd2 --- /dev/null +++ b/src/regex/backend/re2.cc @@ -0,0 +1,98 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2019 + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ +#include +#include +#include +#include + +#include "src/regex/backend/re2.h" +#include "src/regex/regex_match.h" + +namespace modsecurity { +namespace regex { +namespace backend { + +#ifdef WITH_RE2 + +static RE2::Options get_re2_options() { + RE2::Options res; + + res.set_dot_nl(true); + + return res; +} + + +Re2::Re2(const std::string& pattern_) + : pattern(pattern_.empty() ? ".*" : pattern_), + re(pattern, get_re2_options()) +{ +} + +std::list Re2::searchAll(const std::string& s) const { + std::list retList; + + re2::StringPiece subject(s); + + size_t offset = 0; + while (offset <= s.size()) { + int ngroups = re.NumberOfCapturingGroups() + 1; + re2::StringPiece submatches[ngroups]; + + if (!re.Match(subject, offset, s.size(), RE2::UNANCHORED, + &submatches[0], ngroups)) { + break; + } + + for (int i = 0; i < ngroups; i++) { + // N.B. StringPiece::as_string returns value, not reference + auto match_string = submatches[i].as_string(); + auto start = &submatches[i][0] - &subject[0]; + retList.push_front(RegexMatch(std::move(match_string), start)); + } + + offset = (&submatches[0][0] - &subject[0]) + submatches[0].length(); + if (submatches[0].size() == 0) { + offset++; + } + } + + return retList; +} + +int Re2::search(const std::string& s, RegexMatch *match) const { + re2::StringPiece subject(s); + re2::StringPiece submatches[1]; + if (re.Match(subject, 0, s.size(), RE2::UNANCHORED, &submatches[0], 1)) { + // N.B. StringPiece::as_string returns value, not reference + auto match_string = submatches[0].as_string(); + auto start = &submatches[0][0] - &subject[0]; + *match = RegexMatch(std::move(match_string), start); + return 1; + } else { + return 0; + } +} + +int Re2::search(const std::string& s) const { + re2::StringPiece subject(s); + return re.Match(subject, 0, s.size(), RE2::UNANCHORED, NULL, 0); +} +#endif + +} // namespace backend +} // namespace regex +} // namespace modsecurity + diff --git a/src/regex/backend/re2.h b/src/regex/backend/re2.h new file mode 100644 index 00000000..7c08d2cd --- /dev/null +++ b/src/regex/backend/re2.h @@ -0,0 +1,57 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2019 + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#ifdef WITH_RE2 +#include +#endif + +#include +#include + +#include "src/regex/regex_match.h" + +#ifndef SRC_REGEX_BACKEND_RE2_H_ +#define SRC_REGEX_BACKEND_RE2_H_ + +namespace modsecurity { +namespace regex { +namespace backend { + +#ifdef WITH_RE2 + +class Re2 { + public: + explicit Re2(const std::string& pattern_); + + // RE2 class is not copyable, so neither is this + Re2(const Re2&) = delete; + Re2& operator=(const Re2&) = delete; + + std::list searchAll(const std::string& s) const; + int search(const std::string &s, RegexMatch *m) const; + int search(const std::string &s) const; + + const std::string pattern; + private: + const RE2 re; +}; + +#endif + +} // namespace backend +} // namespace regex +} // namespace modsecurity + +#endif // SRC_REGEX_BACKEND_PCRE_H_ diff --git a/src/regex/regex.h b/src/regex/regex.h index 9dc970f3..83448fc8 100644 --- a/src/regex/regex.h +++ b/src/regex/regex.h @@ -21,6 +21,7 @@ #include #include "src/regex/backend/pcre.h" +#include "src/regex/backend/re2.h" #include "src/regex/regex_match.h" #ifndef SRC_REGEX_REGEX_H_ @@ -33,7 +34,7 @@ namespace regex { #ifdef WITH_PCRE using selectedBackend = backend::Pcre; #elif WITH_RE2 -//using selectedBackend = backend::Re2; +using selectedBackend = backend::Re2; #else #error "no regex backend selected" #endif