From a5ee59f5d08fe5fad5bff3222acb8aa1f165433c Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Fri, 18 Jan 2019 18:42:15 -0300 Subject: [PATCH] regex: Organizes the classes per file moves Pcre to backends/pcre.cc moves PegexMatch to regex_match.h --- build/pcre.m4 | 51 +++++++++++++------ src/regex/backend/pcre.cc | 101 ++++++++++++++++++++++++++++++++++++-- src/regex/backend/pcre.h | 26 ++++++++++ src/regex/regex.cc | 88 --------------------------------- src/regex/regex.h | 50 ++++--------------- src/regex/regex_match.h | 46 +++++++++++++++++ 6 files changed, 214 insertions(+), 148 deletions(-) create mode 100644 src/regex/regex_match.h diff --git a/build/pcre.m4 b/build/pcre.m4 index 0de3c9c9..0bff1755 100644 --- a/build/pcre.m4 +++ b/build/pcre.m4 @@ -23,6 +23,16 @@ AC_ARG_WITH( AC_MSG_CHECKING([for libpcre config script]) +if test "x${with_pcre}" == "xno"; then + AC_MSG_NOTICE([Support for PCRE was disabled by the utilization of --without-pcre or --with-pcre=no]) + PCRE_DISABLED=yes +else + if test "x${with_pcre}" == "xyes"; then + PCRE_MANDATORY=yes + AC_MSG_NOTICE([PCRE support was marked as mandatory by the utilization of --with-pcre=yes]) + test_paths="/usr/local/libpcre /usr/local/pcre /usr/local /opt/libpcre /opt/pcre /opt /usr /opt/local" + fi + for x in ${test_paths}; do dnl # Determine if the script was specified and use it directly if test ! -d "$x" -a -e "$x"; then @@ -55,7 +65,7 @@ if test -n "${pcre_path}"; then AC_MSG_RESULT([${PCRE_CONFIG}]) PCRE_VERSION="`${PCRE_CONFIG} --version`" if test ! -z "${PCRE_VERSION}"; then AC_MSG_NOTICE(pcre VERSION: $PCRE_VERSION); fi - PCRE_CFLAGS="`${PCRE_CONFIG} --cflags`" + PCRE_CFLAGS="`${PCRE_CONFIG} --cflags` -DWITH_PCRE" if test ! -z "${PCRE_CFLAGS}"; then AC_MSG_NOTICE(pcre CFLAGS: $PCRE_CFLAGS); fi PCRE_LDADD="`${PCRE_CONFIG} --libs`" if test ! -z "${PCRE_LDADD}"; then AC_MSG_NOTICE(pcre LDADD: $PCRE_LDADD); fi @@ -90,20 +100,31 @@ if test -n "${PCRE_VERSION}"; then LDFLAGS=$save_$LDFLAGS fi -AC_SUBST(PCRE_CONFIG) -AC_SUBST(PCRE_VERSION) -AC_SUBST(PCRE_CPPFLAGS) -AC_SUBST(PCRE_CFLAGS) -AC_SUBST(PCRE_LDFLAGS) -AC_SUBST(PCRE_LDADD) -AC_SUBST(PCRE_LD_PATH) +fi -if test -z "${PCRE_VERSION}"; then - AC_MSG_NOTICE([*** pcre library not found.]) - ifelse([$2], , AC_MSG_ERROR([pcre library is required]), $2) + +if test -z "${PCRE_LDADD}"; then + if test -z "${PCRE_MANDATORY}"; then + if test -z "${PCRE_DISABLED}"; then + PCRE_FOUND=0 + else + PCRE_FOUND=2 + fi + else + AC_MSG_ERROR([PCRE was explicitly referenced but it was not found]) + PCRE_FOUND=-1 + fi else - AC_MSG_NOTICE([using pcre v${PCRE_VERSION}]) - ifelse([$1], , , $1) - PCRE_LDADD="${PCRE_LDADD} -lpcre" -fi + PCRE_FOUND=1 + AC_SUBST(PCRE_CONFIG) + AC_SUBST(PCRE_VERSION) + AC_SUBST(PCRE_CPPFLAGS) + AC_SUBST(PCRE_CFLAGS) + AC_SUBST(PCRE_LDFLAGS) + AC_SUBST(PCRE_LDADD) + AC_SUBST(PCRE_LD_PATH) + PCRE_DISPLAY="${PCRE_LDADD}, ${PCRE_CFLAGS}" + AC_SUBST(PCRE_DISPLAY) +fi + ]) diff --git a/src/regex/backend/pcre.cc b/src/regex/backend/pcre.cc index 78dd8ecd..87352967 100644 --- a/src/regex/backend/pcre.cc +++ b/src/regex/backend/pcre.cc @@ -13,23 +13,114 @@ * */ -#include #include #include #include #include +#include + +#include "src/regex/backend/pcre.h" +#include "src/regex/regex_match.h" -#ifndef SRC_REGEX_BACKEND_PCRE_H_ -#define SRC_REGEX_BACKEND_PCRE_H_ namespace modsecurity { namespace regex { +namespace backend { +#if PCRE_HAVE_JIT +#define pcre_study_opt PCRE_STUDY_JIT_COMPILE +#else +#define pcre_study_opt 0 +#endif + +Pcre::Pcre(const std::string& pattern_) + : pattern(pattern_.empty() ? ".*" : pattern_) { + const char *errptr = NULL; + int erroffset; + + m_pc = pcre_compile(pattern.c_str(), PCRE_DOTALL|PCRE_MULTILINE, + &errptr, &erroffset, NULL); + + m_pce = pcre_study(m_pc, pcre_study_opt, &errptr); +} + + +Pcre::~Pcre() { + if (m_pc != NULL) { + pcre_free(m_pc); + m_pc = NULL; + } + if (m_pce != NULL) { +#if PCRE_HAVE_JIT + pcre_free_study(m_pce); +#else + pcre_free(m_pce); +#endif + m_pce = NULL; + } +} + + +std::list Pcre::searchAll(const std::string& s) const { + const char *subject = s.c_str(); + const std::string tmpString = std::string(s.c_str(), s.size()); + int ovector[OVECCOUNT]; + int rc, i, offset = 0; + std::list retList; + + do { + rc = pcre_exec(m_pc, m_pce, subject, + s.size(), offset, 0, ovector, OVECCOUNT); + + for (i = 0; i < rc; i++) { + size_t start = ovector[2*i]; + size_t end = ovector[2*i+1]; + size_t len = end - start; + if (end > s.size()) { + rc = 0; + break; + } + std::string match = std::string(tmpString, start, len); + offset = start + len; + retList.push_front(RegexMatch(match, start)); + + if (len == 0) { + rc = 0; + break; + } + } + } while (rc > 0); + + return retList; +} + + +int Pcre::search(const std::string& s, RegexMatch *match) const { + int ovector[OVECCOUNT]; + int ret = pcre_exec(m_pc, m_pce, s.c_str(), + s.size(), 0, 0, ovector, OVECCOUNT) > 0; + + if (ret > 0) { + *match = RegexMatch( + std::string(s, ovector[ret-1], ovector[ret] - ovector[ret-1]), + 0); + } + + return ret; +} + + +int Pcre::search(const std::string& s) const { + int ovector[OVECCOUNT]; + return pcre_exec(m_pc, m_pce, s.c_str(), + s.size(), 0, 0, ovector, OVECCOUNT) > 0; +} + + +} // namespace backend } // namespace regex } // namespace modsecurity - -#endif // SRC_REGEX_BACKEND_PCRE_H_ diff --git a/src/regex/backend/pcre.h b/src/regex/backend/pcre.h index 78dd8ecd..4e0af16b 100644 --- a/src/regex/backend/pcre.h +++ b/src/regex/backend/pcre.h @@ -20,14 +20,40 @@ #include #include +#include "src/regex/regex_match.h" + #ifndef SRC_REGEX_BACKEND_PCRE_H_ #define SRC_REGEX_BACKEND_PCRE_H_ namespace modsecurity { namespace regex { +namespace backend { +#define OVECCOUNT 30 + +class Pcre { + public: + explicit Pcre(const std::string& pattern_); + ~Pcre(); + + // m_pc and m_pce can't be easily copied + Pcre(const Pcre&) = delete; + Pcre& operator=(const Pcre&) = 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: + pcre *m_pc = NULL; + pcre_extra *m_pce = NULL; +}; + + +} // namespace backend } // namespace regex } // namespace modsecurity diff --git a/src/regex/regex.cc b/src/regex/regex.cc index 403f230e..22530a05 100644 --- a/src/regex/regex.cc +++ b/src/regex/regex.cc @@ -26,98 +26,10 @@ #include #include -#include "src/utils/geo_lookup.h" - -#if PCRE_HAVE_JIT -#define pcre_study_opt PCRE_STUDY_JIT_COMPILE -#else -#define pcre_study_opt 0 -#endif namespace modsecurity { namespace regex { -Regex::Regex(const std::string& pattern_) - : pattern(pattern_.empty() ? ".*" : pattern_) { - const char *errptr = NULL; - int erroffset; - - m_pc = pcre_compile(pattern.c_str(), PCRE_DOTALL|PCRE_MULTILINE, - &errptr, &erroffset, NULL); - - m_pce = pcre_study(m_pc, pcre_study_opt, &errptr); -} - - -Regex::~Regex() { - if (m_pc != NULL) { - pcre_free(m_pc); - m_pc = NULL; - } - if (m_pce != NULL) { -#if PCRE_HAVE_JIT - pcre_free_study(m_pce); -#else - pcre_free(m_pce); -#endif - m_pce = NULL; - } -} - - -std::list Regex::searchAll(const std::string& s) const { - const char *subject = s.c_str(); - const std::string tmpString = std::string(s.c_str(), s.size()); - int ovector[OVECCOUNT]; - int rc, i, offset = 0; - std::list retList; - - do { - rc = pcre_exec(m_pc, m_pce, subject, - s.size(), offset, 0, ovector, OVECCOUNT); - - for (i = 0; i < rc; i++) { - size_t start = ovector[2*i]; - size_t end = ovector[2*i+1]; - size_t len = end - start; - if (end > s.size()) { - rc = 0; - break; - } - std::string match = std::string(tmpString, start, len); - offset = start + len; - retList.push_front(RegexMatch(match, start)); - - if (len == 0) { - rc = 0; - break; - } - } - } while (rc > 0); - - return retList; -} - -int Regex::search(const std::string& s, RegexMatch *match) const { - int ovector[OVECCOUNT]; - int ret = pcre_exec(m_pc, m_pce, s.c_str(), - s.size(), 0, 0, ovector, OVECCOUNT) > 0; - - if (ret > 0) { - *match = RegexMatch( - std::string(s, ovector[ret-1], ovector[ret] - ovector[ret-1]), - 0); - } - - return ret; -} - -int Regex::search(const std::string& s) const { - int ovector[OVECCOUNT]; - return pcre_exec(m_pc, m_pce, s.c_str(), - s.size(), 0, 0, ovector, OVECCOUNT) > 0; -} - } // namespace regex } // namespace modsecurity diff --git a/src/regex/regex.h b/src/regex/regex.h index dd579a36..bfb988f0 100644 --- a/src/regex/regex.h +++ b/src/regex/regex.h @@ -13,13 +13,16 @@ * */ -#include + #include #include #include #include +#include "src/regex/backend/pcre.h" +#include "src/regex/regex_match.h" + #ifndef SRC_REGEX_REGEX_H_ #define SRC_REGEX_REGEX_H_ @@ -27,48 +30,15 @@ namespace modsecurity { namespace regex { +using selectedBackend = backend::Pcre; -#define OVECCOUNT 30 - -class RegexMatch { - public: - RegexMatch() : - m_match(), - m_offset(0) { } - - RegexMatch(const std::string &match, size_t offset) : - m_match(match), - m_offset(offset) { } - - const std::string& str() const { return m_match; } - size_t offset() const { return m_offset; } - - private: - std::string m_match; - size_t m_offset; +class Regex : public selectedBackend { + public: + explicit Regex(const std::string& pattern) : + selectedBackend(pattern) { }; + ~Regex() { }; }; - -class Regex { - public: - explicit Regex(const std::string& pattern_); - ~Regex(); - - // m_pc and m_pce can't be easily copied - Regex(const Regex&) = delete; - Regex& operator=(const Regex&) = 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: - pcre *m_pc = NULL; - pcre_extra *m_pce = NULL; -}; - - } // namespace regex } // namespace modsecurity diff --git a/src/regex/regex_match.h b/src/regex/regex_match.h new file mode 100644 index 00000000..1263e158 --- /dev/null +++ b/src/regex/regex_match.h @@ -0,0 +1,46 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * 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. + * + */ + + +#ifndef SRC_REGEX_REGEX_MATCH_H_ +#define SRC_REGEX_REGEX_MATCH_H_ + +namespace modsecurity { +namespace regex { + + +class RegexMatch { + public: + RegexMatch() : + m_match(), + m_offset(0) { } + + RegexMatch(const std::string &match, size_t offset) : + m_match(match), + m_offset(offset) { } + + const std::string& str() const { return m_match; } + size_t offset() const { return m_offset; } + + private: + std::string m_match; + size_t m_offset; +}; + + +} // namespace regex +} // namespace modsecurity + +#endif // SRC_REGEX_REGEX_MATCH_H_