From 8e3e9b8be7a17e2de7a3106281f40204e64f6cc5 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Tue, 5 Mar 2019 12:26:44 -0300 Subject: [PATCH] Makes operator to use string_view --- headers/modsecurity/anchored_set_variable.h | 9 + headers/modsecurity/anchored_variable.h | 6 + headers/modsecurity/string_view.hpp | 1422 +++++++++++++++++++ src/Makefile.am | 2 + src/anchored_set_variable.cc | 30 + src/anchored_variable.cc | 24 + src/engine/lua.cc | 2 +- src/operators/begins_with.cc | 6 +- src/operators/begins_with.h | 4 +- src/operators/contains.cc | 8 +- src/operators/contains.h | 8 +- src/operators/contains_word.cc | 27 +- src/operators/contains_word.h | 7 +- src/operators/detect_sqli.cc | 22 +- src/operators/detect_sqli.h | 5 +- src/operators/detect_xss.cc | 18 +- src/operators/detect_xss.h | 5 +- src/operators/ends_with.cc | 12 +- src/operators/ends_with.h | 6 +- src/operators/eq.cc | 7 +- src/operators/eq.h | 6 +- src/operators/fuzzy_hash.cc | 9 +- src/operators/fuzzy_hash.h | 7 +- src/operators/ge.cc | 8 +- src/operators/ge.h | 6 +- src/operators/geo_lookup.cc | 13 +- src/operators/geo_lookup.h | 10 +- src/operators/gsblookup.cc | 5 +- src/operators/gsblookup.h | 5 +- src/operators/gt.cc | 7 +- src/operators/gt.h | 6 +- src/operators/inspect_file.cc | 9 +- src/operators/inspect_file.h | 9 +- src/operators/ip_match.cc | 7 +- src/operators/ip_match.h | 5 +- src/operators/le.cc | 7 +- src/operators/le.h | 5 +- src/operators/lt.cc | 7 +- src/operators/lt.h | 5 +- src/operators/no_match.cc | 5 +- src/operators/no_match.h | 5 +- src/operators/operator.cc | 29 +- src/operators/operator.h | 30 +- src/operators/pm.cc | 8 +- src/operators/pm.h | 6 +- src/operators/pm_from_file.cc | 2 +- src/operators/rbl.cc | 23 +- src/operators/rbl.h | 6 +- src/operators/rsub.cc | 5 +- src/operators/rsub.h | 6 +- src/operators/rx.cc | 12 +- src/operators/rx.h | 7 +- src/operators/rx_global.cc | 4 +- src/operators/rx_global.h | 2 +- src/operators/str_eq.cc | 7 +- src/operators/str_eq.h | 5 +- src/operators/str_match.cc | 7 +- src/operators/str_match.h | 5 +- src/operators/unconditional_match.cc | 4 +- src/operators/unconditional_match.h | 5 +- src/operators/validate_byte_range.cc | 27 +- src/operators/validate_byte_range.h | 8 +- src/operators/validate_dtd.cc | 26 +- src/operators/validate_dtd.h | 6 +- src/operators/validate_hash.cc | 5 +- src/operators/validate_hash.h | 6 +- src/operators/validate_schema.cc | 28 +- src/operators/validate_schema.h | 6 +- src/operators/validate_url_encoding.cc | 15 +- src/operators/validate_url_encoding.h | 5 +- src/operators/validate_utf8_encoding.cc | 18 +- src/operators/validate_utf8_encoding.h | 5 +- src/operators/verify_cc.cc | 18 +- src/operators/verify_cc.h | 9 +- src/operators/verify_cpf.cc | 14 +- src/operators/verify_cpf.h | 5 +- src/operators/verify_ssn.cc | 14 +- src/operators/verify_ssn.h | 5 +- src/operators/verify_svnr.cc | 8 +- src/operators/verify_svnr.h | 5 +- src/operators/within.cc | 8 +- src/operators/within.h | 7 +- src/rule_with_operator.cc | 30 +- src/rule_with_operator.h | 12 +- test/cppcheck_suppressions.txt | 13 +- 85 files changed, 1954 insertions(+), 298 deletions(-) create mode 100644 headers/modsecurity/string_view.hpp diff --git a/headers/modsecurity/anchored_set_variable.h b/headers/modsecurity/anchored_set_variable.h index 5b41e850..367e40f2 100644 --- a/headers/modsecurity/anchored_set_variable.h +++ b/headers/modsecurity/anchored_set_variable.h @@ -27,10 +27,13 @@ #include #include #include + +#include "modsecurity/string_view.hpp" #endif #include "modsecurity/variable_value.h" + #ifndef HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_H_ #define HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_H_ @@ -79,6 +82,12 @@ class AnchoredSetVariable : public std::unordered_multimap #include #include +#include + +#include "modsecurity/string_view.hpp" #endif #include "modsecurity/variable_value.h" + #ifndef HEADERS_MODSECURITY_ANCHORED_VARIABLE_H_ #define HEADERS_MODSECURITY_ANCHORED_VARIABLE_H_ @@ -59,6 +63,8 @@ class AnchoredVariable { void unset(); void set(const std::string &a, size_t offset); + void set(const bpstd::string_view &a, size_t offset); + void set(const char *a, size_t offset); void set(const std::string &a, size_t offset, size_t offsetLen); void append(const std::string &a, size_t offset, bool spaceSeparator = false); diff --git a/headers/modsecurity/string_view.hpp b/headers/modsecurity/string_view.hpp new file mode 100644 index 00000000..ce992953 --- /dev/null +++ b/headers/modsecurity/string_view.hpp @@ -0,0 +1,1422 @@ +/** + * \file string_view.hpp + * + * \brief This header contains the definition of the string_view type, as + * described by the C++17 standard. + * + * \author Matthew Rodusek (matthew.rodusek@gmail.com) + * \copyright Matthew Rodusek + */ + +/* + * The MIT License (MIT) + * + * Licensed under the MIT License . + * Copyright (c) 2016 Matthew Rodusek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef BPSTD_STRING_VIEW_HPP +#define BPSTD_STRING_VIEW_HPP + +#include // std:: +#include // std::char_traits +#include // std::basic_ostream +#include // std::size_t +#include // std::allocator +#include // std::out_of_range +#include // std::reverse_iterator +namespace bpstd { // back-port std + + //////////////////////////////////////////////////////////////////////////// + /// \brief A wrapper around non-owned strings. + /// + /// This is an implementation of the C++17 string_view proposal + /// + /// \ingroup core + //////////////////////////////////////////////////////////////////////////// + template< + typename CharT, + typename Traits = std::char_traits + > + class basic_string_view final + { + //------------------------------------------------------------------------ + // Public Member Types + //------------------------------------------------------------------------ + public: + + using char_type = CharT; + using traits_type = Traits; + using size_type = std::size_t; + + using value_type = CharT; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + + using iterator = const CharT*; + using const_iterator = const CharT*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + //------------------------------------------------------------------------ + // Public Members + //------------------------------------------------------------------------ + public: + + static constexpr size_type npos = size_type(-1); + + //------------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------------ + public: + + /// \brief Default constructs a basic_string_view without any content + constexpr basic_string_view() noexcept; + + /// \brief Constructs a basic_string_view by copying another one + /// + /// \param other the string view being copied + constexpr basic_string_view(const basic_string_view& other) noexcept = default; + + /// \brief Constructs a basic_string_view by moving anothe rone + /// + /// \param other the string view being moved + constexpr basic_string_view(basic_string_view&& other) noexcept = default; + + /// \brief Constructs a basic_string_view from a std::basic_string + /// + /// \param str the string to view + template + basic_string_view(const std::basic_string& str) noexcept; + + /// \brief Constructs a basic_string_view from an ansi-string + /// + /// \param str the string to view + constexpr basic_string_view(const char_type* str) noexcept; + + /// \brief Constructs a basic_string_view from an ansi string of a given size + /// + /// \param str the string to view + /// \param count the size of the string + constexpr basic_string_view(const char_type* str, size_type count) noexcept; + + //------------------------------------------------------------------------ + // Assignment + //------------------------------------------------------------------------ + public: + + /// \brief Assigns a basic_string_view from an ansi-string + /// + /// \param view the string to view + /// \return reference to \c (*this) + basic_string_view& operator=(const basic_string_view& view) = default; + + //------------------------------------------------------------------------ + // Capacity + //------------------------------------------------------------------------ + public: + + /// \brief Returns the length of the string, in terms of bytes + /// + /// \return the length of the string, in terms of bytes + constexpr size_type size() const noexcept; + + /// \copydoc basic_string_view::size + constexpr size_type length() const noexcept; + + /// \brief The largest possible number of char-like objects that can be + /// referred to by a basic_string_view. + /// \return Maximum number of characters + constexpr size_type max_size() const noexcept; + + /// \brief Returns whether the basic_string_view is empty + /// (i.e. whether its length is 0). + /// + /// \return whether the basic_string_view is empty + constexpr bool empty() const noexcept; + + //------------------------------------------------------------------------ + // Element Access + //------------------------------------------------------------------------ + public: + + /// \brief Gets the ansi-string of the current basic_string_view + /// + /// \return the ansi-string pointer + constexpr const char_type* c_str() const noexcept; + + /// \brief Gets the data of the current basic_string_view + /// + /// \note This is an alias of #c_str + /// + /// \return the data this basic_string_view contains + constexpr const char_type* data() const noexcept; + + /// \brief Accesses the element at index \p pos + /// + /// \param pos the index to access + /// \return const reference to the character + constexpr const_reference operator[](size_type pos) const noexcept; + + /// \brief Accesses the element at index \p pos + /// + /// \param pos the index to access + /// \return const reference to the character + constexpr const_reference at(size_type pos) const; + + /// \brief Access the first character of the string + /// + /// \note Undefined behavior if basic_string_view is empty + /// + /// \return reference to the first character of the string + constexpr const_reference front() const noexcept; + + /// \brief References the last character of the string + /// + /// \note Undefined behavior if basic_string_view is empty + /// + /// \return reference to the last character of the string + constexpr const_reference back() const noexcept; + + //------------------------------------------------------------------------ + // Modifiers + //------------------------------------------------------------------------ + public: + + /// \brief Moves the start of the view forward by n characters. + /// + /// The behavior is undefined if n > size(). + /// + /// \param n number of characters to remove from the start of the view + void remove_prefix(size_type n) noexcept; + + /// \brief Moves the end of the view back by n characters. + /// + /// The behavior is undefined if n > size(). + /// + /// \param n number of characters to remove from the end of the view + void remove_suffix(size_type n) noexcept; + + /// \brief Exchanges the view with that of v. + /// + /// \param v view to swap with + void swap(basic_string_view& v) noexcept; + + //------------------------------------------------------------------------ + // Conversions + //------------------------------------------------------------------------ + public: + + /// \brief Creates a basic_string with a copy of the content of the current view. + /// + /// \tparam Allocator type used to allocate internal storage + /// \param a Allocator instance to use for allocating the new string + /// + /// \return A basic_string containing a copy of the characters of the current view. + template> + constexpr std::basic_string + to_string(const Allocator& a = Allocator()) const; + + /// \copydoc basic_string_view::to_string + template + explicit constexpr operator std::basic_string() const; + + //------------------------------------------------------------------------ + // Operations + //------------------------------------------------------------------------ + public: + + /// \brief Copies the substring [pos, pos + rcount) to the character string pointed + /// to by dest, where rcount is the smaller of count and size() - pos. + /// + /// \param dest pointer to the destination character string + /// \param count requested substring length + /// \param pos position of the first character + size_type copy( char_type* dest, + size_type count = npos, + size_type pos = 0 ) const; + + /// \brief Returns a substring of this viewed string + /// + /// \param pos the position of the first character in the substring + /// \param len the length of the substring + /// \return the created substring + basic_string_view substr(size_t pos = 0, size_t len = npos) const; + + //------------------------------------------------------------------------ + + /// \brief Compares two character sequences + /// + /// \param v view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(basic_string_view v) const noexcept; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count number of characters of this view to compare + /// \param v view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(size_type pos, size_type count, basic_string_view v) const; + + /// \brief Compares two character sequences + /// + /// \param pos1 position of the first character in this view to compare + /// \param count1 number of characters of this view to compare + /// \param v view to compare + /// \param pos2 position of the second character in this view to compare + /// \param count2 number of characters of the given view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare( size_type pos1, size_type count1, basic_string_view v, + size_type pos2, size_type count2 ) const; + + /// \brief Compares two character sequences + /// + /// \param s pointer to the character string to compare to + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(const char_type* s) const; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count number of characters of this view to compare + /// \param s pointer to the character string to compare to + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(size_type pos, size_type count, const char_type* s) const; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count1 number of characters of this view to compare + /// \param s pointer to the character string to compare to + /// \param count2 number of characters of the given view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare( size_type pos, size_type count1, const char_type* s, + size_type count2 ) const; + + //------------------------------------------------------------------------ + + size_type find(basic_string_view v, size_type pos = 0) const; + + size_type find(char_type c, size_type pos = 0) const; + + size_type find(const char_type* s, size_type pos, size_type count) const; + + size_type find(const char_type* s, size_type pos = 0) const; + + //------------------------------------------------------------------------ + + size_type rfind(basic_string_view v, size_type pos = npos) const; + + size_type rfind(char_type c, size_type pos = npos) const; + + size_type rfind(const char_type* s, size_type pos, size_type count) const; + + size_type rfind(const char_type* s, size_type pos = npos) const; + + //------------------------------------------------------------------------ + + size_type find_first_of(basic_string_view v, size_type pos = 0) const; + + size_type find_first_of(char_type c, size_type pos = 0) const; + + size_type find_first_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_first_of(const char_type* s, size_type pos = 0) const; + + //------------------------------------------------------------------------ + + size_type find_last_of(basic_string_view v, size_type pos = npos) const; + + size_type find_last_of(char_type c, size_type pos = npos) const; + + size_type find_last_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_last_of(const char_type* s, size_type pos = npos) const; + + //------------------------------------------------------------------------ + + size_type find_first_not_of(basic_string_view v, size_type pos = 0) const; + + size_type find_first_not_of(char_type c, size_type pos = 0) const; + + size_type find_first_not_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_first_not_of(const char_type* s, size_type pos = 0) const; + + //------------------------------------------------------------------------ + + size_type find_last_not_of(basic_string_view v, size_type pos = npos) const; + + size_type find_last_not_of(char_type c, size_type pos = npos) const; + + size_type find_last_not_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_last_not_of(const char_type* s, size_type pos = npos) const; + + //------------------------------------------------------------------------ + // Iterators + //------------------------------------------------------------------------ + public: + + /// \{ + /// \brief Retrieves the begin iterator for this basic_string_view + /// + /// \return the begin iterator + const_iterator begin() const noexcept; + const_iterator cbegin() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the end iterator for this basic_string_view + /// + /// \return the end iterator + const_iterator end() const noexcept; + const_iterator cend() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the reverse begin iterator for this basic_string_view + /// + /// \return the reverse begin iterator + const_reverse_iterator rbegin() const noexcept; + const_reverse_iterator rend() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the reverse end iterator for this basic_string_view + /// + /// \return the reverse end iterator + const_reverse_iterator crbegin() const noexcept; + const_reverse_iterator crend() const noexcept; + /// \} + + //------------------------------------------------------------------------ + // Private Member + //------------------------------------------------------------------------ + private: + + const char_type* m_str; ///< The internal string type + size_type m_size; ///< The size of this string + + /// \brief Checks whether \p c is one of the characters in \p str + /// + /// \param c the character to check + /// \param str the characters to compare against + /// \return true if \p c is one of the characters in \p str + static bool is_one_of(CharT c, basic_string_view str); + }; + + template + const typename basic_string_view::size_type + basic_string_view::npos; + + //-------------------------------------------------------------------------- + // Public Functions + //-------------------------------------------------------------------------- + + /// \brief Overload for ostream output of basic_string_view + /// + /// \param o The output stream to print to + /// \param str the string to print + /// \return reference to the output stream + template + std::basic_ostream& operator<<(std::basic_ostream& o, + const basic_string_view& str); + + template + void swap(basic_string_view& lhs, + basic_string_view& rhs) noexcept; + + //-------------------------------------------------------------------------- + // Comparison Functions + //-------------------------------------------------------------------------- + + template + bool operator==(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator!=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator<(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator>(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator<=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator>=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + + //-------------------------------------------------------------------------- + // Type Aliases + //-------------------------------------------------------------------------- + + using string_view = basic_string_view; + using wstring_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + +} // namespace bpstd + +#ifndef BPSTD_DETAIL_STRING_VIEW_INL +#define BPSTD_DETAIL_STRING_VIEW_INL + +namespace bpstd { + + //-------------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------------- + + template + inline constexpr basic_string_view::basic_string_view() + noexcept + : m_str(nullptr), + m_size(0) + { + + } + + template + template + inline basic_string_view::basic_string_view(const std::basic_string& str) + noexcept + : m_str(str.c_str()), + m_size(str.size()) + { + + } + + template + inline constexpr basic_string_view::basic_string_view(const char_type* str) + noexcept + : m_str(str), + m_size(traits_type::length(str)) + { + + } + + template + inline constexpr basic_string_view::basic_string_view(const char_type* str, size_type count) + noexcept + : m_str(str), + m_size(count) + { + + } + + //-------------------------------------------------------------------------- + // Capacity + //-------------------------------------------------------------------------- + + template + inline constexpr typename basic_string_view::size_type + basic_string_view::size() + const noexcept + { + return m_size; + } + + template + inline constexpr typename basic_string_view::size_type + basic_string_view::length() + const noexcept + { + return size(); + } + + template + inline constexpr typename basic_string_view::size_type + basic_string_view::max_size() + const noexcept + { + return npos - 1; + } + + template + inline constexpr bool basic_string_view::empty() + const noexcept + { + return m_size == 0; + } + + //-------------------------------------------------------------------------- + // Element Access + //-------------------------------------------------------------------------- + + template + inline constexpr const typename basic_string_view::char_type* + basic_string_view::c_str() + const noexcept + { + return m_str; + } + + template + inline constexpr const typename basic_string_view::char_type* + basic_string_view::data() + const noexcept + { + return m_str; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::operator[](size_type pos) + const noexcept + { + return m_str[pos]; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::at(size_type pos) + const + { + return pos < m_size ? m_str[pos] : throw std::out_of_range("Input out of range in basic_string_view::at"), m_str[pos]; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::front( ) + const noexcept + { + return *m_str; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::back( ) + const noexcept + { + return m_str[m_size-1]; + } + + //-------------------------------------------------------------------------- + // Modifiers + //-------------------------------------------------------------------------- + + template + inline void + basic_string_view::remove_prefix(size_type n) + noexcept + { + m_str += n, m_size -= n; + } + + template + inline void + basic_string_view::remove_suffix(size_type n) + noexcept + { + m_size -= n; + } + + template + inline void + basic_string_view::swap(basic_string_view& v) + noexcept + { + using std::swap; + swap(m_size,v.m_size); + swap(m_str,v.m_str); + } + + //-------------------------------------------------------------------------- + // Conversions + //-------------------------------------------------------------------------- + + template + template + inline constexpr std::basic_string + basic_string_view::to_string(const Allocator& a) + const + { + return std::basic_string(m_str, m_size, a); + } + + template + template + inline constexpr basic_string_view::operator + std::basic_string() + const + { + return std::basic_string(m_str, m_size); + } + + //-------------------------------------------------------------------------- + // String Operations + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::copy(char_type* dest, + size_type count, + size_type pos) + const + { + if(pos >= m_size) { + throw std::out_of_range("Index out of range in basic_string_view::copy"); + } + + const size_type rcount = std::min(m_size - pos,count+1); + std::copy( m_str + pos, m_str + pos + rcount, dest); + return rcount; + } + + template + inline basic_string_view + basic_string_view::substr(size_type pos, + size_type len) + const + { + const size_type max_length = pos > m_size ? 0 : m_size - pos; + + if (pos > size()) { + throw std::out_of_range("Index out of range in basic_string_view::substr"); + } + + return basic_string_view(m_str + pos, std::min(len, max_length) ); + } + + //-------------------------------------------------------------------------- + + template + inline int basic_string_view::compare(basic_string_view v) + const noexcept + { + const size_type rlen = std::min(m_size,v.m_size); + const int compare = Traits::compare(m_str,v.m_str,rlen); + + return (compare ? compare : (m_size < v.m_size ? -1 : (m_size > v.m_size ? 1 : 0))); + } + + template + inline int basic_string_view::compare(size_type pos, + size_type count, + basic_string_view v) + const + { + return substr(pos,count).compare(v); + } + + template + inline int basic_string_view::compare(size_type pos1, + size_type count1, + basic_string_view v, + size_type pos2, + size_type count2) + const + { + return substr(pos1,count1).compare(v.substr(pos2,count2)); + } + + template + inline int basic_string_view::compare(const char_type* s) + const + { + return compare(basic_string_view(s)); + } + + template + inline int basic_string_view::compare(size_type pos, + size_type count, + const char_type* s) + const + { + return substr(pos, count).compare(basic_string_view(s)); + } + + template + inline int basic_string_view::compare(size_type pos, + size_type count1, + const char_type* s, + size_type count2) + const + { + return substr(pos, count1).compare(basic_string_view(s, count2)); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find(basic_string_view v, + size_type pos) + const + { + // Can't find a substring if the substring is bigger than this + if (pos > size()) { + return npos; + } + if ((pos + v.size()) > size()) { + return npos; + } + + const auto offset = pos; + const auto increments = size() - v.size(); + + for (auto i = 0u; i <= increments; ++i) { + const auto j = i + offset; + if (substr(j, v.size()) == v) { + return j; + } + } + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find(char_type c, + size_type pos) + const + { + return find(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find(const char_type* s, size_type pos, + size_type count) + const + { + return find(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find(const char_type* s, + size_type pos) + const + { + return find(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(basic_string_view v, + size_type pos) + const + { + if (empty()) { + return v.empty() ? 0u : npos; + } + if (v.empty()) { + return std::min(size() - 1, pos); + } + if (v.size() > size()) { + return npos; + } + + auto i = std::min(pos, (size() - v.size())); + while (i != npos) { + if (substr(i, v.size()) == v) { + return i; + } + --i; + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(char_type c, + size_type pos) + const + { + return rfind(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(const char_type* s, size_type pos, + size_type count) + const + { + return rfind(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(const char_type* s, + size_type pos) + const + { + return rfind(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(basic_string_view v, + size_type pos) + const + { + const auto max_index = size(); + for (auto i = pos; i < max_index; ++i) { + if (is_one_of(m_str[i],v)) { + return i; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(char_type c, + size_type pos) + const + { + return find_first_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(const char_type* s, size_type pos, + size_type count) + const + { + return find_first_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(const char_type* s, + size_type pos) + const + { + return find_first_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(basic_string_view v, + size_type pos) + const + { + if (empty()) { + return npos; + } + const auto max_index = std::min(size() - 1, pos); + for (auto i = 0u; i <= max_index; ++i) { + const auto j = max_index - i; + + if (is_one_of(m_str[j],v)) { + return j; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(char_type c, + size_type pos) + const + { + return find_last_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(const char_type* s, size_type pos, + size_type count) + const + { + return find_last_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(const char_type* s, + size_type pos) + const + { + return find_last_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(basic_string_view v, + size_type pos) + const + { + const auto max_index = size(); + for (auto i = pos; i < max_index; ++i) { + if (!is_one_of(m_str[i],v)) { + return i; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(char_type c, + size_type pos) + const + { + return find_first_not_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(const char_type* s, + size_type pos, + size_type count) + const + { + return find_first_not_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(const char_type* s, + size_type pos) + const + { + return find_first_not_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(basic_string_view v, + size_type pos) + const + { + if (empty()) { + return npos; + } + const auto max_index = std::min(size() - 1, pos); + for (auto i = 0u; i <= max_index; ++i) { + const auto j = max_index - i; + + if (!is_one_of(m_str[j],v)) { + return j; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(char_type c, + size_type pos) + const + { + return find_last_not_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(const char_type* s, + size_type pos, + size_type count) + const + { + return find_last_not_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(const char_type* s, + size_type pos) + const + { + return find_last_not_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + // Iterator + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::const_iterator + basic_string_view::begin() + const noexcept + { + return m_str; + } + + template + inline typename basic_string_view::const_iterator + basic_string_view::cbegin() + const noexcept + { + return begin(); + } + + template + inline typename basic_string_view::const_iterator + basic_string_view::end() + const noexcept + { + return m_str + m_size; + } + + template + inline typename basic_string_view::const_iterator + basic_string_view::cend() + const noexcept + { + return cend(); + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::rbegin() + const noexcept + { + return const_reverse_iterator{end()}; + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::crbegin() + const noexcept + { + return rbegin(); + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::rend() + const noexcept + { + return const_reverse_iterator{begin()}; + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::crend() + const noexcept + { + return crend(); + } + + template + inline bool basic_string_view::is_one_of(CharT c, + basic_string_view str) + { + for (auto s : str) { + if (c == s) { + return true; + } + } + return false; + } + + //-------------------------------------------------------------------------- + // Public Functions + //-------------------------------------------------------------------------- + + template + std::basic_ostream& operator<<(std::basic_ostream& o, + const basic_string_view& str) + { + o.write(str.data(),str.size()); + return o; + } + + template + inline void swap(basic_string_view& lhs, + basic_string_view& rhs) + noexcept + { + lhs.swap(rhs); + } + + //-------------------------------------------------------------------------- + // Comparison Functions + //-------------------------------------------------------------------------- + + template + inline bool operator==(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) == 0; + } + + template + inline bool operator==(basic_string_view lhs, + const CharT* rhs) + noexcept + { + return lhs == basic_string_view(rhs); + } + + template + inline bool operator==(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) == rhs; + } + + template + inline bool operator==(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) == rhs; + } + + template + inline bool operator==(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs == basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator!=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) != 0; + } + + template + inline bool operator!=(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs != basic_string_view(rhs); + } + + template + inline bool operator!=(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) != rhs; + } + + template + inline bool operator!=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) != rhs; + } + + template + inline bool operator!=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs != basic_string_view(rhs); + } + //-------------------------------------------------------------------------- + + template + inline bool operator<(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) < 0; + } + + template + inline bool operator<(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs < basic_string_view(rhs); + } + + template + inline bool operator<(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) < rhs; + } + + template + inline bool operator<(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) < rhs; + } + + template + inline bool operator<(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs < basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator>(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) > 0; + } + + template + inline bool operator>(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs > basic_string_view(rhs); + } + + template + inline bool operator>(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) > rhs; + } + + template + inline bool operator>(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) > rhs; + } + + template + inline bool operator>(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs > basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator<=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) <= 0; + } + + template + inline bool operator<=(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs <= basic_string_view(rhs); + } + + template + inline bool operator<=(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) <= rhs; + } + + template + inline bool operator<=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) <= rhs; + } + + template + inline bool operator<=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs <= basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator>=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) >= 0; + } + + template + inline bool operator>=(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs >= basic_string_view(rhs); + } + + template + inline bool operator>=(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) >= rhs; + } + + template + inline bool operator>=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) >= rhs; + } + + template + inline bool operator>=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs >= basic_string_view(rhs); + } + +} // namespace bpstd + +#endif /* BPSTD_DETAIL_STRING_VIEW_INL */ + +#endif /* BPSTD_STRING_VIEW_HPP */ diff --git a/src/Makefile.am b/src/Makefile.am index b8ee0e7d..1a6f1b88 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,11 +49,13 @@ pkginclude_HEADERS = \ ../headers/modsecurity/rules_set_phases.h \ ../headers/modsecurity/rules_set_properties.h \ ../headers/modsecurity/rules_exceptions.h \ + ../headers/modsecurity/string_view.hpp \ ../headers/modsecurity/transaction.h \ ../headers/modsecurity/variable_origin.h \ ../headers/modsecurity/variable_value.h + libmodsecurity_includesub_collection_HEADERS = \ ../headers/modsecurity/collection/collection.h \ ../headers/modsecurity/collection/collections.h diff --git a/src/anchored_set_variable.cc b/src/anchored_set_variable.cc index 32bddf88..1ba31b38 100644 --- a/src/anchored_set_variable.cc +++ b/src/anchored_set_variable.cc @@ -80,6 +80,36 @@ void AnchoredSetVariable::set(const std::string &key, } +void AnchoredSetVariable::set(const std::string &key, + const bpstd::string_view &value, size_t offset) { + std::unique_ptr origin(new VariableOrigin()); + std::string *v = new std::string(value.c_str()); + VariableValue *var = new VariableValue(&m_name, &key, v); + delete v; + + origin->m_offset = offset; + origin->m_length = value.size(); + + var->addOrigin(std::move(origin)); + emplace(key, var); +} + + +void AnchoredSetVariable::set(const std::string &key, + const char *value, size_t offset) { + std::unique_ptr origin(new VariableOrigin()); + std::string *v = new std::string(value); + VariableValue *var = new VariableValue(&m_name, &key, v); + delete v; + + origin->m_offset = offset; + origin->m_length = strlen(value); + + var->addOrigin(std::move(origin)); + emplace(key, var); +} + + void AnchoredSetVariable::resolve( std::vector *l) { for (const auto& x : *this) { diff --git a/src/anchored_variable.cc b/src/anchored_variable.cc index 63128bb2..4c385321 100644 --- a/src/anchored_variable.cc +++ b/src/anchored_variable.cc @@ -23,6 +23,7 @@ #include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" #include "src/utils/regex.h" +#include "modsecurity/string_view.hpp" namespace modsecurity { @@ -75,6 +76,29 @@ void AnchoredVariable::set(const std::string &a, size_t offset) { } +void AnchoredVariable::set(const char *a, size_t offset) { + std::unique_ptr origin(new VariableOrigin()); + + m_offset = offset; + m_value.assign(a, strlen(a)); + origin->m_offset = offset; + origin->m_length = m_value.size(); + m_var->addOrigin(std::move(origin)); +} + + +void AnchoredVariable::set(const bpstd::string_view &a, size_t offset) { + std::unique_ptr origin(new VariableOrigin()); + + m_offset = offset; + m_value.assign(a.c_str(), a.size()); + origin->m_offset = offset; + origin->m_length = m_value.size(); + + m_var->addOrigin(std::move(origin)); +} + + void AnchoredVariable::append(const std::string &a, size_t offset, bool spaceSeparator) { std::unique_ptr origin( diff --git a/src/engine/lua.cc b/src/engine/lua.cc index e8525d13..a28e6b76 100644 --- a/src/engine/lua.cc +++ b/src/engine/lua.cc @@ -444,12 +444,12 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, in.assign(newVar.c_str(), newVar.size()); tfn->execute(t, in, out); newVar.assign(out.c_str(), out.size()); + delete tfn; } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ + std::string(name)); } - delete tfn; } return newVar; diff --git a/src/operators/begins_with.cc b/src/operators/begins_with.cc index 7cf8909d..09571b70 100644 --- a/src/operators/begins_with.cc +++ b/src/operators/begins_with.cc @@ -24,8 +24,10 @@ namespace modsecurity { namespace operators { -bool BeginsWith::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, RuleMessage *ruleMessage) { +bool BeginsWith::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); if (str.size() < p.size()) { diff --git a/src/operators/begins_with.h b/src/operators/begins_with.h index db8755ca..58bb7512 100644 --- a/src/operators/begins_with.h +++ b/src/operators/begins_with.h @@ -32,7 +32,9 @@ class BeginsWith : public Operator { explicit BeginsWith(std::unique_ptr param) : Operator("BeginsWith", std::move(param)) { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, const std::string &str, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; }; diff --git a/src/operators/contains.cc b/src/operators/contains.cc index 828e7ac6..15e61ab5 100644 --- a/src/operators/contains.cc +++ b/src/operators/contains.cc @@ -21,10 +21,12 @@ namespace modsecurity { namespace operators { -bool Contains::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, RuleMessage *ruleMessage) { +bool Contains::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - size_t offset = input.find(p); + size_t offset = input.to_string().find(p); bool contains = offset != std::string::npos; diff --git a/src/operators/contains.h b/src/operators/contains.h index 0144e418..505f8a1e 100644 --- a/src/operators/contains.h +++ b/src/operators/contains.h @@ -33,9 +33,11 @@ class Contains : public Operator { public: /** @ingroup ModSecurity_Operator */ explicit Contains(std::unique_ptr param) - : Operator("Contains", std::move(param)) { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, + : Operator("Contains", std::move(param)) { }; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; }; diff --git a/src/operators/contains_word.cc b/src/operators/contains_word.cc index b691d62e..2a5d7ab9 100644 --- a/src/operators/contains_word.cc +++ b/src/operators/contains_word.cc @@ -23,7 +23,7 @@ namespace modsecurity { namespace operators { -bool ContainsWord::acceptableChar(const std::string& a, size_t pos) { +bool ContainsWord::acceptableChar(const bpstd::string_view &a, size_t pos) { if (a.size() - 1 < pos) { return false; } @@ -36,37 +36,40 @@ bool ContainsWord::acceptableChar(const std::string& a, size_t pos) { return true; } -bool ContainsWord::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, RuleMessage *ruleMessage) { +bool ContainsWord::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &inputView, + RuleMessage *ruleMessage) { std::string paramTarget(m_string->evaluate(transaction)); + std::string input = inputView.to_string(); if (paramTarget.empty()) { return true; } - if (str.empty()) { + if (input.empty()) { return false; } - if (str == paramTarget) { + if (input == paramTarget) { return true; } - size_t pos = str.find(paramTarget); + size_t pos = input.find(paramTarget); while (pos != std::string::npos) { - if (pos == 0 && acceptableChar(str, paramTarget.size())) { + if (pos == 0 && acceptableChar(input, paramTarget.size())) { logOffset(ruleMessage, 0, paramTarget.size()); return true; } - if (pos + paramTarget.size() == str.size() && - acceptableChar(str, pos - 1)) { + if (pos + paramTarget.size() == input.size() && + acceptableChar(input, pos - 1)) { logOffset(ruleMessage, pos, paramTarget.size()); return true; } - if (acceptableChar(str, pos - 1) && - acceptableChar(str, pos + paramTarget.size())) { + if (acceptableChar(input, pos - 1) && + acceptableChar(input, pos + paramTarget.size())) { logOffset(ruleMessage, pos, paramTarget.size()); return true; } - pos = str.find(paramTarget, pos + 1); + pos = input.find(paramTarget, pos + 1); } return false; diff --git a/src/operators/contains_word.h b/src/operators/contains_word.h index 20ee3ff8..30177bf3 100644 --- a/src/operators/contains_word.h +++ b/src/operators/contains_word.h @@ -32,12 +32,13 @@ class ContainsWord : public Operator { explicit ContainsWord(std::unique_ptr param) : Operator("ContainsWord", std::move(param)) { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; private: - static bool acceptableChar(const std::string& a, size_t pos); + static bool acceptableChar(const bpstd::string_view &a, size_t pos); }; } // namespace operators diff --git a/src/operators/detect_sqli.cc b/src/operators/detect_sqli.cc index 68b51c48..29d43a3c 100644 --- a/src/operators/detect_sqli.cc +++ b/src/operators/detect_sqli.cc @@ -27,31 +27,33 @@ namespace modsecurity { namespace operators { -bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, RuleMessage *ruleMessage) { +bool DetectSQLi::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { char fingerprint[8]; int issqli; issqli = libinjection_sqli(input.c_str(), input.length(), fingerprint); - if (!t) { + if (!transaction) { goto tisempty; } if (issqli) { - t->m_matched.push_back(fingerprint); - ms_dbg_a(t, 4, "detected SQLi using libinjection with " \ + transaction->m_matched.push_back(fingerprint); + ms_dbg_a(transaction, 4, "detected SQLi using libinjection with " \ "fingerprint '" + std::string(fingerprint) + "' at: '" + - input + "'"); + input.to_string() + "'"); if (rule && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(fingerprint)); - ms_dbg_a(t, 7, "Added DetectSQLi match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added DetectSQLi match TX.0: " + \ std::string(fingerprint)); } } else { - ms_dbg_a(t, 9, "detected SQLi: not able to find an " \ - "inject on '" + input + "'"); + ms_dbg_a(transaction, 9, "detected SQLi: not able to find an " \ + "inject on '" + input.to_string() + "'"); } tisempty: diff --git a/src/operators/detect_sqli.h b/src/operators/detect_sqli.h index 9ab7a7c1..a7df9ded 100644 --- a/src/operators/detect_sqli.h +++ b/src/operators/detect_sqli.h @@ -32,8 +32,9 @@ class DetectSQLi : public Operator { m_match_message.assign("detected SQLi using libinjection."); } - bool evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; }; diff --git a/src/operators/detect_xss.cc b/src/operators/detect_xss.cc index 38341ae3..7bc3c9eb 100644 --- a/src/operators/detect_xss.cc +++ b/src/operators/detect_xss.cc @@ -26,24 +26,26 @@ namespace modsecurity { namespace operators { -bool DetectXSS::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, RuleMessage *ruleMessage) { +bool DetectXSS::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { int is_xss; is_xss = libinjection_xss(input.c_str(), input.length()); - if (t) { + if (transaction) { if (is_xss) { - ms_dbg_a(t, 5, "detected XSS using libinjection."); + ms_dbg_a(transaction, 5, "detected XSS using libinjection."); if (rule && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(input)); - ms_dbg_a(t, 7, "Added DetectXSS match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added DetectXSS match TX.0: " + \ std::string(input)); } } else { - ms_dbg_a(t, 9, "libinjection was not able to " \ - "find any XSS in: " + input); + ms_dbg_a(transaction, 9, "libinjection was not able to " \ + "find any XSS in: " + input.to_string()); } } return is_xss != 0; diff --git a/src/operators/detect_xss.h b/src/operators/detect_xss.h index 16bddb22..1f4f0339 100644 --- a/src/operators/detect_xss.h +++ b/src/operators/detect_xss.h @@ -31,8 +31,9 @@ class DetectXSS : public Operator { m_match_message.assign("detected XSS using libinjection."); } - bool evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; }; diff --git a/src/operators/ends_with.cc b/src/operators/ends_with.cc index 125fef6a..d8c36fd4 100644 --- a/src/operators/ends_with.cc +++ b/src/operators/ends_with.cc @@ -23,16 +23,18 @@ namespace modsecurity { namespace operators { -bool EndsWith::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, RuleMessage *ruleMessage) { +bool EndsWith::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { bool ret = false; std::string p(m_string->evaluate(transaction)); - if (str.length() >= p.length()) { - ret = (0 == str.compare(str.length() - p.length(), + if (input.length() >= p.length()) { + ret = (0 == input.compare(input.length() - p.length(), p.length(), p)); if (ret) { - logOffset(ruleMessage, str.length() - p.length(), + logOffset(ruleMessage, input.length() - p.length(), p.size()); } } diff --git a/src/operators/ends_with.h b/src/operators/ends_with.h index 1fd55595..c376f49c 100644 --- a/src/operators/ends_with.h +++ b/src/operators/ends_with.h @@ -33,8 +33,10 @@ class EndsWith : public Operator { : Operator("EndsWith", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; }; diff --git a/src/operators/eq.cc b/src/operators/eq.cc index 473356d3..7513b73b 100644 --- a/src/operators/eq.cc +++ b/src/operators/eq.cc @@ -24,7 +24,10 @@ namespace modsecurity { namespace operators { -bool Eq::evaluate(Transaction *transaction, const std::string &input) { +bool Eq::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { int p = 0; int i = 0; std::string pt(m_string->evaluate(transaction)); @@ -35,7 +38,7 @@ bool Eq::evaluate(Transaction *transaction, const std::string &input) { p = 0; } try { - i = std::stoi(input); + i = std::stoi(input.c_str()); } catch (...) { i = 0; } diff --git a/src/operators/eq.h b/src/operators/eq.h index 02494f6f..578e0796 100644 --- a/src/operators/eq.h +++ b/src/operators/eq.h @@ -31,7 +31,11 @@ class Eq : public Operator { /** @ingroup ModSecurity_Operator */ explicit Eq(std::unique_ptr param) : Operator("Eq", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &input) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/fuzzy_hash.cc b/src/operators/fuzzy_hash.cc index df31a98c..f4c13594 100644 --- a/src/operators/fuzzy_hash.cc +++ b/src/operators/fuzzy_hash.cc @@ -96,21 +96,24 @@ FuzzyHash::~FuzzyHash() { } -bool FuzzyHash::evaluate(Transaction *t, const std::string &str) { +bool FuzzyHash::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { #ifdef WITH_SSDEEP char result[FUZZY_MAX_RESULT]; struct fuzzy_hash_chunk *chunk = m_head; if (fuzzy_hash_buf((const unsigned char*)str.c_str(), str.size(), result)) { - ms_dbg_a(t, 4, "Problems generating fuzzy hash"); + ms_dbg_a(transaction, 4, "Problems generating fuzzy hash"); return false; } while (chunk != NULL) { int i = fuzzy_compare(chunk->data, result); if (i >= m_threshold) { - ms_dbg_a(t, 4, "Fuzzy hash: matched " \ + ms_dbg_a(transaction, 4, "Fuzzy hash: matched " \ "with score: " + std::to_string(i) + "."); return true; } diff --git a/src/operators/fuzzy_hash.h b/src/operators/fuzzy_hash.h index b555eff5..d007906b 100644 --- a/src/operators/fuzzy_hash.h +++ b/src/operators/fuzzy_hash.h @@ -44,9 +44,12 @@ class FuzzyHash : public Operator { m_head(NULL) { } ~FuzzyHash(); - bool evaluate(Transaction *transaction, const std::string &std) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; - bool init(const std::string ¶m, std::string *error) override; + bool init(const std::string &file, std::string *error) override; private: int m_threshold; struct fuzzy_hash_chunk *m_head; diff --git a/src/operators/ge.cc b/src/operators/ge.cc index 2a3b39ec..acd03334 100644 --- a/src/operators/ge.cc +++ b/src/operators/ge.cc @@ -23,11 +23,13 @@ namespace modsecurity { namespace operators { -bool Ge::evaluate(Transaction *transaction, const std::string &input) { +bool Ge::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - std::string i = input; - bool ge = atoll(i.c_str()) >= atoll(p.c_str()); + bool ge = atoll(str.c_str()) >= atoll(p.c_str()); return ge; } diff --git a/src/operators/ge.h b/src/operators/ge.h index 4830e91e..6716f3d4 100644 --- a/src/operators/ge.h +++ b/src/operators/ge.h @@ -32,7 +32,11 @@ class Ge : public Operator { : Operator("Ge", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/geo_lookup.cc b/src/operators/geo_lookup.cc index 5717b7af..c79591fb 100644 --- a/src/operators/geo_lookup.cc +++ b/src/operators/geo_lookup.cc @@ -34,16 +34,19 @@ namespace modsecurity { namespace operators { -bool GeoLookup::evaluate(Transaction *trans, const std::string &exp) { +bool GeoLookup::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { using std::placeholders::_1; using std::placeholders::_2; bool ret = true; - if (trans) { - ret = Utils::GeoLookup::getInstance().lookup(exp, trans, - std::bind(&GeoLookup::debug, this, trans, _1, _2)); + if (transaction) { + ret = Utils::GeoLookup::getInstance().lookup(str.c_str(), transaction, + std::bind(&GeoLookup::debug, this, transaction, _1, _2)); } else { - ret = Utils::GeoLookup::getInstance().lookup(exp, NULL, + ret = Utils::GeoLookup::getInstance().lookup(str.c_str(), NULL, nullptr); } diff --git a/src/operators/geo_lookup.h b/src/operators/geo_lookup.h index e0193782..ffbbacd2 100644 --- a/src/operators/geo_lookup.h +++ b/src/operators/geo_lookup.h @@ -29,11 +29,15 @@ class GeoLookup : public Operator { /** @ingroup ModSecurity_Operator */ GeoLookup() : Operator("GeoLookup") { } - bool evaluate(Transaction *transaction, const std::string &exp) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; protected: - bool debug(Transaction *transaction, int x, const std::string &a) { - ms_dbg_a(transaction, x, a); + bool debug(Transaction *transaction, int x, const bpstd::string_view &str) { + ms_dbg_a(transaction, x, str.to_string()); return true; } }; diff --git a/src/operators/gsblookup.cc b/src/operators/gsblookup.cc index ca934b47..98eaefba 100644 --- a/src/operators/gsblookup.cc +++ b/src/operators/gsblookup.cc @@ -23,7 +23,10 @@ namespace modsecurity { namespace operators { -bool GsbLookup::evaluate(Transaction *transaction, const std::string &str) { +bool GsbLookup::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { /** * @todo Implement the operator GeoLookup. * Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#gsblookup diff --git a/src/operators/gsblookup.h b/src/operators/gsblookup.h index 63c32ae2..c25a445e 100644 --- a/src/operators/gsblookup.h +++ b/src/operators/gsblookup.h @@ -31,7 +31,10 @@ class GsbLookup : public Operator { explicit GsbLookup(std::unique_ptr param) : Operator("GsbLookup", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/gt.cc b/src/operators/gt.cc index 47bb2fb7..edbbc03e 100644 --- a/src/operators/gt.cc +++ b/src/operators/gt.cc @@ -23,10 +23,13 @@ namespace modsecurity { namespace operators { -bool Gt::evaluate(Transaction *transaction, const std::string &input) { +bool Gt::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool gt = atoll(input.c_str()) > atoll(p.c_str()); + bool gt = atoll(str.c_str()) > atoll(p.c_str()); return gt; } diff --git a/src/operators/gt.h b/src/operators/gt.h index 0e80853f..969f8259 100644 --- a/src/operators/gt.h +++ b/src/operators/gt.h @@ -33,7 +33,11 @@ class Gt : public Operator { : Operator("Gt", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/inspect_file.cc b/src/operators/inspect_file.cc index 9ce43af0..2d2cd963 100644 --- a/src/operators/inspect_file.cc +++ b/src/operators/inspect_file.cc @@ -49,9 +49,12 @@ bool InspectFile::init(const std::string ¶m2, std::string *error) { } -bool InspectFile::evaluate(Transaction *transaction, const std::string &str) { +bool InspectFile::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { if (m_isScript) { - return m_lua.run(transaction, str); + return m_lua.run(transaction, str.c_str()); } else { FILE *in; char buff[512]; @@ -61,7 +64,7 @@ bool InspectFile::evaluate(Transaction *transaction, const std::string &str) { openstr.append(m_param); openstr.append(" "); - openstr.append(str); + openstr.append(str.c_str()); if (!(in = popen(openstr.c_str(), "r"))) { return false; } diff --git a/src/operators/inspect_file.h b/src/operators/inspect_file.h index e398eb30..7b1f16f2 100644 --- a/src/operators/inspect_file.h +++ b/src/operators/inspect_file.h @@ -35,8 +35,13 @@ class InspectFile : public Operator { m_file(""), m_isScript(false) { } - bool init(const std::string ¶m, std::string *error) override; - bool evaluate(Transaction *transaction, const std::string &str) override; + bool init(const std::string &file, std::string *error) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + private: std::string m_file; bool m_isScript; diff --git a/src/operators/ip_match.cc b/src/operators/ip_match.cc index 35a993fb..9a739507 100644 --- a/src/operators/ip_match.cc +++ b/src/operators/ip_match.cc @@ -37,8 +37,11 @@ bool IpMatch::init(const std::string &file, std::string *error) { } -bool IpMatch::evaluate(Transaction *transaction, const std::string &input) { - return m_tree.contains(input); +bool IpMatch::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { + return m_tree.contains(str.c_str()); } diff --git a/src/operators/ip_match.h b/src/operators/ip_match.h index b0c080c7..72d55e2e 100644 --- a/src/operators/ip_match.h +++ b/src/operators/ip_match.h @@ -34,7 +34,10 @@ class IpMatch : public Operator { IpMatch(const std::string &n, std::unique_ptr param) : Operator(n, std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; bool init(const std::string &file, std::string *error) override; diff --git a/src/operators/le.cc b/src/operators/le.cc index e448a383..fe9c96da 100644 --- a/src/operators/le.cc +++ b/src/operators/le.cc @@ -23,10 +23,13 @@ namespace modsecurity { namespace operators { -bool Le::evaluate(Transaction *transaction, const std::string &input) { +bool Le::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool le = atoll(input.c_str()) <= atoll(p.c_str()); + bool le = atoll(str.c_str()) <= atoll(p.c_str()); return le; } diff --git a/src/operators/le.h b/src/operators/le.h index 2549112e..f9ecd7e5 100644 --- a/src/operators/le.h +++ b/src/operators/le.h @@ -34,7 +34,10 @@ class Le : public Operator { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; diff --git a/src/operators/lt.cc b/src/operators/lt.cc index 2cb05c6c..715898a2 100644 --- a/src/operators/lt.cc +++ b/src/operators/lt.cc @@ -22,10 +22,13 @@ namespace modsecurity { namespace operators { -bool Lt::evaluate(Transaction *transaction, const std::string &input) { +bool Lt::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool lt = atoll(input.c_str()) < atoll(p.c_str()); + bool lt = atoll(str.c_str()) < atoll(p.c_str()); return lt; } diff --git a/src/operators/lt.h b/src/operators/lt.h index aa5c4b82..d83f03dd 100644 --- a/src/operators/lt.h +++ b/src/operators/lt.h @@ -34,7 +34,10 @@ class Lt : public Operator { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/no_match.cc b/src/operators/no_match.cc index 4509bf5f..3fcb77c7 100644 --- a/src/operators/no_match.cc +++ b/src/operators/no_match.cc @@ -20,7 +20,10 @@ namespace modsecurity { namespace operators { -bool NoMatch::evaluate(Transaction *transaction, const std::string &str) { +bool NoMatch::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { return false; } diff --git a/src/operators/no_match.h b/src/operators/no_match.h index e6012cb3..b8728105 100644 --- a/src/operators/no_match.h +++ b/src/operators/no_match.h @@ -32,7 +32,10 @@ class NoMatch : public Operator { NoMatch() : Operator("NoMatch") { } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/operator.cc b/src/operators/operator.cc index 2aaa143a..b45d0035 100644 --- a/src/operators/operator.cc +++ b/src/operators/operator.cc @@ -71,7 +71,7 @@ namespace operators { bool Operator::evaluateInternal(Transaction *transaction, - RuleWithActions *rule, const std::string& a, RuleMessage *rm) { + RuleWithActions *rule, const bpstd::string_view &a, RuleMessage *rm) { bool res = evaluate(transaction, rule, a, rm); if (m_negation) { @@ -81,28 +81,6 @@ bool Operator::evaluateInternal(Transaction *transaction, return res; } -bool Operator::evaluateInternal(Transaction *transaction, - RuleWithActions *rule, const std::string& a) { - bool res = evaluate(transaction, rule, a); - - if (m_negation) { - return !res; - } - - return res; -} - -bool Operator::evaluateInternal(Transaction *transaction, - const std::string& a) { - bool res = evaluate(transaction, a); - - if (m_negation) { - return !res; - } - - return res; -} - std::string Operator::resolveMatchMessage(Transaction *t, std::string key, std::string value) { @@ -132,7 +110,10 @@ std::string Operator::resolveMatchMessage(Transaction *t, } -bool Operator::evaluate(Transaction *transaction, const std::string& a) { +bool Operator::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { ms_dbg_a(transaction, 2, "Operator: " + m_op + \ " is not implemented or malfunctioning."); return true; diff --git a/src/operators/operator.h b/src/operators/operator.h index 44437794..405567e6 100644 --- a/src/operators/operator.h +++ b/src/operators/operator.h @@ -24,6 +24,7 @@ #include "modsecurity/rule.h" #include "modsecurity/rule_message.h" #include "src/run_time_string.h" +#include "modsecurity/string_view.hpp" namespace modsecurity { namespace operators { @@ -107,26 +108,17 @@ class Operator { return true; } - virtual std::string resolveMatchMessage(Transaction *t, - std::string key, std::string value); + bool evaluateInternal(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view& a, + RuleMessage *ruleMessage); - bool evaluateInternal(Transaction *t, const std::string& a); - bool evaluateInternal(Transaction *t, RuleWithActions *rule, - const std::string& a); - bool evaluateInternal(Transaction *t, RuleWithActions *rule, - const std::string& a, RuleMessage *ruleMessage); + virtual bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage); - virtual bool evaluate(Transaction *transaction, const std::string &str); - virtual bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str) { - return evaluate(transaction, str); - } - virtual bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, RuleMessage *ruleMessage) { - return evaluate(transaction, str); - } - static void logOffset(RuleMessage *ruleMessage, int offset, int len) { if (ruleMessage) { ruleMessage->m_reference.append("o" @@ -135,6 +127,10 @@ class Operator { } } + virtual std::string resolveMatchMessage(Transaction *t, + std::string key, std::string value); + + std::string m_match_message; bool m_negation; std::string m_op; diff --git a/src/operators/pm.cc b/src/operators/pm.cc index 0e24abc6..412c5985 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -83,8 +83,10 @@ void Pm::postOrderTraversal(acmp_btree_node_t *node) { } -bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, RuleMessage *ruleMessage) { +bool Pm::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { int rc = -1; ACMPT pt; pt.parser = m_p; @@ -93,7 +95,7 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, #ifdef MODSEC_MUTEX_ON_PM pthread_mutex_lock(&m_lock); #endif - rc = acmp_process_quick(&pt, &match, input.c_str(), input.length()); + rc = acmp_process_quick(&pt, &match, str.c_str(), str.length()); #ifdef MODSEC_MUTEX_ON_PM pthread_mutex_unlock(&m_lock); #endif diff --git a/src/operators/pm.h b/src/operators/pm.h index 34ff688a..b34cf1c7 100644 --- a/src/operators/pm.h +++ b/src/operators/pm.h @@ -41,8 +41,10 @@ class Pm : public Operator { m_p = acmp_create(0); } ~Pm(); - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; diff --git a/src/operators/pm_from_file.cc b/src/operators/pm_from_file.cc index f70677cd..097e901f 100644 --- a/src/operators/pm_from_file.cc +++ b/src/operators/pm_from_file.cc @@ -56,7 +56,7 @@ bool PmFromFile::init(const std::string &config, std::string *error) { iss = new std::stringstream(client.content); } else { std::string err; - std::string resource = utils::find_resource(m_param, config, &err); + std::string resource = utils::find_resource(m_param, config.c_str(), &err); iss = new std::ifstream(resource, std::ios::in); if (((std::ifstream *)iss)->is_open() == false) { diff --git a/src/operators/rbl.cc b/src/operators/rbl.cc index ecc484eb..19f7cdd5 100644 --- a/src/operators/rbl.cc +++ b/src/operators/rbl.cc @@ -202,11 +202,12 @@ void Rbl::furtherInfo(struct sockaddr_in *sin, const std::string &ipStr, } -bool Rbl::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& ipStr, - RuleMessage *ruleMessage) { +bool Rbl::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { struct addrinfo *info = NULL; - std::string host = Rbl::mapIpToAddress(ipStr, t); + std::string host = Rbl::mapIpToAddress(str.c_str(), transaction); int rc = 0; if (host.empty()) { @@ -219,20 +220,20 @@ bool Rbl::evaluate(Transaction *t, RuleWithActions *rule, if (info != NULL) { freeaddrinfo(info); } - ms_dbg_a(t, 5, "RBL lookup of " + ipStr + " failed."); + ms_dbg_a(transaction, 5, "RBL lookup of " + str.to_string() + " failed."); return false; } struct sockaddr *addr = info->ai_addr; struct sockaddr_in *sin = (struct sockaddr_in *) addr; - furtherInfo(sin, ipStr, t, m_provider); + furtherInfo(sin, str.c_str(), transaction, m_provider); freeaddrinfo(info); - if (rule && t && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( - "0", std::string(ipStr)); - ms_dbg_a(t, 7, "Added RXL match TX.0: " + \ - std::string(ipStr)); + if (rule && transaction && rule->hasCaptureAction()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( + "0", std::string(str)); + ms_dbg_a(transaction, 7, "Added RXL match TX.0: " + \ + std::string(str)); } return true; diff --git a/src/operators/rbl.h b/src/operators/rbl.h index eb25c56b..74a32db6 100644 --- a/src/operators/rbl.h +++ b/src/operators/rbl.h @@ -76,8 +76,10 @@ class Rbl : public Operator { m_provider = RblProvider::httpbl; } } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; std::string mapIpToAddress(const std::string &ipStr, Transaction *trans) const; diff --git a/src/operators/rsub.cc b/src/operators/rsub.cc index d310185b..979117fe 100644 --- a/src/operators/rsub.cc +++ b/src/operators/rsub.cc @@ -23,7 +23,10 @@ namespace modsecurity { namespace operators { -bool Rsub::evaluate(Transaction *transaction, const std::string &str) { +bool Rsub::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { /** * @todo Implement the operator Rsub. * Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#rsub diff --git a/src/operators/rsub.h b/src/operators/rsub.h index 15c80085..84981a73 100644 --- a/src/operators/rsub.h +++ b/src/operators/rsub.h @@ -32,7 +32,11 @@ class Rsub : public Operator { /** @ingroup ModSecurity_Operator */ explicit Rsub(std::unique_ptr param) : Operator("Rsub", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; diff --git a/src/operators/rx.cc b/src/operators/rx.cc index a0957824..71837079 100644 --- a/src/operators/rx.cc +++ b/src/operators/rx.cc @@ -29,7 +29,7 @@ namespace modsecurity { namespace operators { -bool Rx::init(const std::string &arg, std::string *error) { +bool Rx::init(const std::string &file, std::string *error) { if (m_string->m_containsMacro == false) { m_re = new Regex(m_param); } @@ -38,8 +38,10 @@ bool Rx::init(const std::string &arg, std::string *error) { } -bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, RuleMessage *ruleMessage) { +bool Rx::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { Regex *re; if (m_param.empty() && !m_string->m_containsMacro) { @@ -54,8 +56,8 @@ bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule, } std::vector captures; - re->searchOneMatch(input, captures); - + // FIXME: searchOneMatch should accept string_view. + re->searchOneMatch(input.c_str(), captures); if (rule && rule->hasCaptureAction() && transaction) { for (const Utils::SMatchCapture& capture : captures) { const std::string capture_substring(input.substr(capture.m_offset,capture.m_length)); diff --git a/src/operators/rx.h b/src/operators/rx.h index 3fee464a..874ec1f7 100644 --- a/src/operators/rx.h +++ b/src/operators/rx.h @@ -49,11 +49,12 @@ class Rx : public Operator { } } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; - bool init(const std::string &arg, std::string *error) override; + bool init(const std::string &file, std::string *error) override; private: Regex *m_re; diff --git a/src/operators/rx_global.cc b/src/operators/rx_global.cc index 052c0792..c0c4cee8 100644 --- a/src/operators/rx_global.cc +++ b/src/operators/rx_global.cc @@ -37,7 +37,7 @@ bool RxGlobal::init(const std::string &arg, std::string *error) { bool RxGlobal::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, RuleMessage *ruleMessage) { + const bpstd::string_view& input, RuleMessage *ruleMessage) { Regex *re; if (m_param.empty() && !m_string->m_containsMacro) { @@ -52,7 +52,7 @@ bool RxGlobal::evaluate(Transaction *transaction, RuleWithActions *rule, } std::vector captures; - re->searchGlobal(input, captures); + re->searchGlobal(input.c_str(), captures); if (rule && rule->hasCaptureAction() && transaction) { for (const Utils::SMatchCapture& capture : captures) { diff --git a/src/operators/rx_global.h b/src/operators/rx_global.h index f608773c..a508d34f 100644 --- a/src/operators/rx_global.h +++ b/src/operators/rx_global.h @@ -50,7 +50,7 @@ class RxGlobal : public Operator { } bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, + const bpstd::string_view& input, RuleMessage *ruleMessage) override; bool init(const std::string &arg, std::string *error) override; diff --git a/src/operators/str_eq.cc b/src/operators/str_eq.cc index 13c03688..160c4196 100644 --- a/src/operators/str_eq.cc +++ b/src/operators/str_eq.cc @@ -20,9 +20,12 @@ namespace modsecurity { namespace operators { -bool StrEq::evaluate(Transaction *transaction, const std::string &str) { +bool StrEq::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string pt(m_string->evaluate(transaction)); - return !pt.compare(str); + return !pt.compare(str.to_string()); } diff --git a/src/operators/str_eq.h b/src/operators/str_eq.h index 10f38e3c..05104391 100644 --- a/src/operators/str_eq.h +++ b/src/operators/str_eq.h @@ -34,7 +34,10 @@ class StrEq : public Operator { explicit StrEq(std::unique_ptr param) : Operator("StrEq", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/str_match.cc b/src/operators/str_match.cc index ce7dfb2b..51a2bb28 100644 --- a/src/operators/str_match.cc +++ b/src/operators/str_match.cc @@ -24,9 +24,12 @@ namespace modsecurity { namespace operators { -bool StrMatch::evaluate(Transaction *transaction, const std::string &input) { +bool StrMatch::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool ret = input.find(p) != std::string::npos; + bool ret = str.find(p) != std::string::npos; return ret; } diff --git a/src/operators/str_match.h b/src/operators/str_match.h index 4f77532f..07a25e56 100644 --- a/src/operators/str_match.h +++ b/src/operators/str_match.h @@ -34,7 +34,10 @@ class StrMatch : public Operator { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/unconditional_match.cc b/src/operators/unconditional_match.cc index b79275d2..e68630b6 100644 --- a/src/operators/unconditional_match.cc +++ b/src/operators/unconditional_match.cc @@ -19,7 +19,9 @@ namespace modsecurity { namespace operators { bool UnconditionalMatch::evaluate(Transaction *transaction, - const std::string &input) { + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { return true; } diff --git a/src/operators/unconditional_match.h b/src/operators/unconditional_match.h index a54c7682..fafafa3c 100644 --- a/src/operators/unconditional_match.h +++ b/src/operators/unconditional_match.h @@ -31,7 +31,10 @@ class UnconditionalMatch : public Operator { UnconditionalMatch() : Operator("UnconditionalMatch") { } - bool evaluate(Transaction *transaction, const std::string &exp) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/validate_byte_range.cc b/src/operators/validate_byte_range.cc index 8ab58538..b1a68d2a 100644 --- a/src/operators/validate_byte_range.cc +++ b/src/operators/validate_byte_range.cc @@ -23,7 +23,7 @@ namespace modsecurity { namespace operators { -bool ValidateByteRange::getRange(const std::string &rangeRepresentation, +bool ValidateByteRange::getRange(const bpstd::string_view &rangeRepresentation, std::string *error) { size_t pos = rangeRepresentation.find_first_of("-"); int start; @@ -31,9 +31,10 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation, if (pos == std::string::npos) { try { - start = std::stoi(rangeRepresentation); + start = std::stoi(rangeRepresentation.c_str()); } catch(...) { - error->assign("Not able to convert '" + rangeRepresentation + + error->assign("Not able to convert '" + \ + rangeRepresentation.to_string() + "' into a number"); return false; } @@ -42,19 +43,19 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation, } try { - start = std::stoi(std::string(rangeRepresentation, 0, pos)); + start = std::stoi(std::string(rangeRepresentation.c_str(), 0, pos)); } catch (...) { error->assign("Not able to convert '" + - std::string(rangeRepresentation, 0, pos) + + std::string(rangeRepresentation.c_str(), 0, pos) + "' into a number"); return false; } try { - end = std::stoi(std::string(rangeRepresentation, pos + 1, + end = std::stoi(std::string(rangeRepresentation.c_str(), pos + 1, rangeRepresentation.length() - (pos + 1))); } catch (...) { - error->assign("Not able to convert '" + std::string(rangeRepresentation, + error->assign("Not able to convert '" + std::string(rangeRepresentation.c_str(), pos + 1, rangeRepresentation.length() - (pos + 1)) + "' into a number"); return false; @@ -110,16 +111,18 @@ bool ValidateByteRange::init(const std::string &file, } -bool ValidateByteRange::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, RuleMessage *ruleMessage) { +bool ValidateByteRange::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { bool ret = true; size_t count = 0; - for (int i = 0; i < input.length(); i++) { - int x = (unsigned char) input.at(i); + for (int i = 0; i < str.length(); i++) { + int x = (unsigned char) str.at(i); if (!(table[x >> 3] & (1 << (x & 0x7)))) { // debug(9, "Value " + std::to_string(x) + " in " + - // input + " ouside range: " + param); + // str + " ouside range: " + param); logOffset(ruleMessage, i, 1); count++; } diff --git a/src/operators/validate_byte_range.h b/src/operators/validate_byte_range.h index da053783..fbcf7014 100644 --- a/src/operators/validate_byte_range.h +++ b/src/operators/validate_byte_range.h @@ -37,10 +37,12 @@ class ValidateByteRange : public Operator { } ~ValidateByteRange() override { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; - bool getRange(const std::string &rangeRepresentation, std::string *error); + + bool getRange(const bpstd::string_view &rangeRepresentation, std::string *error); bool init(const std::string& file, std::string *error) override; private: std::vector ranges; diff --git a/src/operators/validate_dtd.cc b/src/operators/validate_dtd.cc index f57dbed3..7d3d0c77 100644 --- a/src/operators/validate_dtd.cc +++ b/src/operators/validate_dtd.cc @@ -43,25 +43,28 @@ bool ValidateDTD::init(const std::string &file, std::string *error) { } -bool ValidateDTD::evaluate(Transaction *t, const std::string &str) { +bool ValidateDTD::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { xmlValidCtxtPtr cvp; m_dtd = xmlParseDTD(NULL, (const xmlChar *)m_resource.c_str()); if (m_dtd == NULL) { std::string err = std::string("XML: Failed to load DTD: ") \ + m_resource; - ms_dbg_a(t, 4, err); + ms_dbg_a(transaction, 4, err); return true; } - if (t->m_xml->m_data.doc == NULL) { - ms_dbg_a(t, 4, "XML document tree could not "\ + if (transaction->m_xml->m_data.doc == NULL) { + ms_dbg_a(transaction, 4, "XML document tree could not "\ "be found for DTD validation."); return true; } - if (t->m_xml->m_data.well_formed != 1) { - ms_dbg_a(t, 4, "XML: DTD validation failed because " \ + if (transaction->m_xml->m_data.well_formed != 1) { + ms_dbg_a(transaction, 4, "XML: DTD validation failed because " \ "content is not well formed."); return true; } @@ -78,22 +81,23 @@ bool ValidateDTD::evaluate(Transaction *t, const std::string &str) { cvp = xmlNewValidCtxt(); if (cvp == NULL) { - ms_dbg_a(t, 4, "XML: Failed to create a validation context."); + ms_dbg_a(transaction, 4, + "XML: Failed to create a validation context."); return true; } /* Send validator errors/warnings to msr_log */ cvp->error = (xmlSchemaValidityErrorFunc)error_runtime; cvp->warning = (xmlSchemaValidityErrorFunc)warn_runtime; - cvp->userData = t; + cvp->userData = transaction; - if (!xmlValidateDtd(cvp, t->m_xml->m_data.doc, m_dtd)) { - ms_dbg_a(t, 4, "XML: DTD validation failed."); + if (!xmlValidateDtd(cvp, transaction->m_xml->m_data.doc, m_dtd)) { + ms_dbg_a(transaction, 4, "XML: DTD validation failed."); xmlFreeValidCtxt(cvp); return true; } - ms_dbg_a(t, 4, std::string("XML: Successfully validated " \ + ms_dbg_a(transaction, 4, std::string("XML: Successfully validated " \ "payload against DTD: ") + m_resource); xmlFreeValidCtxt(cvp); diff --git a/src/operators/validate_dtd.h b/src/operators/validate_dtd.h index ace6aad4..a5cd610b 100644 --- a/src/operators/validate_dtd.h +++ b/src/operators/validate_dtd.h @@ -46,7 +46,11 @@ class ValidateDTD : public Operator { } } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + bool init(const std::string &file, std::string *error) override; diff --git a/src/operators/validate_hash.cc b/src/operators/validate_hash.cc index b608ac2b..3ceaa1ae 100644 --- a/src/operators/validate_hash.cc +++ b/src/operators/validate_hash.cc @@ -22,7 +22,10 @@ namespace modsecurity { namespace operators { -bool ValidateHash::evaluate(Transaction *transaction, const std::string &str) { +bool ValidateHash::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { /** * @todo Implement the operator ValidateHash. * Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#validateHash diff --git a/src/operators/validate_hash.h b/src/operators/validate_hash.h index 47e25fdf..f9de9aa6 100644 --- a/src/operators/validate_hash.h +++ b/src/operators/validate_hash.h @@ -31,7 +31,11 @@ class ValidateHash : public Operator { /** @ingroup ModSecurity_Operator */ explicit ValidateHash(std::unique_ptr param) : Operator("ValidateHash", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/validate_schema.cc b/src/operators/validate_schema.cc index a94ca4f8..182df207 100644 --- a/src/operators/validate_schema.cc +++ b/src/operators/validate_schema.cc @@ -39,8 +39,10 @@ bool ValidateSchema::init(const std::string &file, std::string *error) { } -bool ValidateSchema::evaluate(Transaction *t, - const std::string &str) { +bool ValidateSchema::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { int rc; m_parserCtx = xmlSchemaNewParserCtxt(m_resource.c_str()); @@ -52,7 +54,7 @@ bool ValidateSchema::evaluate(Transaction *t, if (m_err.empty() == false) { err << m_err; } - ms_dbg_a(t, 4, err.str()); + ms_dbg_a(transaction, 4, err.str()); return true; } @@ -75,7 +77,7 @@ bool ValidateSchema::evaluate(Transaction *t, if (m_err.empty() == false) { err << " " << m_err; } - ms_dbg_a(t, 4, err.str()); + ms_dbg_a(transaction, 4, err.str()); xmlSchemaFreeParserCtxt(m_parserCtx); return true; } @@ -86,23 +88,23 @@ bool ValidateSchema::evaluate(Transaction *t, if (m_err.empty() == false) { err << " " << m_err; } - ms_dbg_a(t, 4, err.str()); + ms_dbg_a(transaction, 4, err.str()); return true; } /* Send validator errors/warnings to msr_log */ xmlSchemaSetValidErrors(m_validCtx, (xmlSchemaValidityErrorFunc)error_runtime, - (xmlSchemaValidityWarningFunc)warn_runtime, t); + (xmlSchemaValidityWarningFunc)warn_runtime, transaction); - if (t->m_xml->m_data.doc == NULL) { - ms_dbg_a(t, 4, "XML document tree could not be found for " \ + if (transaction->m_xml->m_data.doc == NULL) { + ms_dbg_a(transaction, 4, "XML document tree could not be found for " \ "schema validation."); return true; } - if (t->m_xml->m_data.well_formed != 1) { - ms_dbg_a(t, 4, "XML: Schema validation failed because " \ + if (transaction->m_xml->m_data.well_formed != 1) { + ms_dbg_a(transaction, 4, "XML: Schema validation failed because " \ "content is not well formed."); return true; } @@ -116,15 +118,15 @@ bool ValidateSchema::evaluate(Transaction *t, } */ - rc = xmlSchemaValidateDoc(m_validCtx, t->m_xml->m_data.doc); + rc = xmlSchemaValidateDoc(m_validCtx, transaction->m_xml->m_data.doc); if (rc != 0) { - ms_dbg_a(t, 4, "XML: Schema validation failed."); + ms_dbg_a(transaction, 4, "XML: Schema validation failed."); xmlSchemaFree(m_schema); xmlSchemaFreeParserCtxt(m_parserCtx); return true; /* No match. */ } - ms_dbg_a(t, 4, "XML: Successfully validated payload against " \ + ms_dbg_a(transaction, 4, "XML: Successfully validated payload against " \ "Schema: " + m_resource); xmlSchemaFree(m_schema); xmlSchemaFreeParserCtxt(m_parserCtx); diff --git a/src/operators/validate_schema.h b/src/operators/validate_schema.h index b190ef15..80d5aaac 100644 --- a/src/operators/validate_schema.h +++ b/src/operators/validate_schema.h @@ -58,7 +58,11 @@ class ValidateSchema : public Operator { } } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + bool init(const std::string &file, std::string *error) override; diff --git a/src/operators/validate_url_encoding.cc b/src/operators/validate_url_encoding.cc index 302ca1f8..c82eb62c 100644 --- a/src/operators/validate_url_encoding.cc +++ b/src/operators/validate_url_encoding.cc @@ -68,8 +68,10 @@ int ValidateUrlEncoding::validate_url_encoding(const char *input, } -bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, RuleMessage *ruleMessage) { +bool ValidateUrlEncoding::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { size_t offset = 0; bool res = false; @@ -82,14 +84,15 @@ bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *ru case 1 : /* Encoding is valid */ if (transaction) { - ms_dbg_a(transaction, 7, "Valid URL Encoding at '" +input + "'"); + ms_dbg_a(transaction, 7, "Valid URL Encoding at '" + \ + input.to_string() + "'"); } res = false; break; case -2 : if (transaction) { ms_dbg_a(transaction, 7, "Invalid URL Encoding: Non-hexadecimal " - "digits used at '" + input + "'"); + "digits used at '" + input.to_string() + "'"); logOffset(ruleMessage, offset, input.size()); } res = true; /* Invalid match. */ @@ -97,7 +100,7 @@ bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *ru case -3 : if (transaction) { ms_dbg_a(transaction, 7, "Invalid URL Encoding: Not enough " \ - "characters at the end of input at '" + input + "'"); + "characters at the end of input at '" + input.to_string() + "'"); logOffset(ruleMessage, offset, input.size()); } res = true; /* Invalid match. */ @@ -107,7 +110,7 @@ bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *ru if (transaction) { ms_dbg_a(transaction, 7, "Invalid URL Encoding: Internal " \ "Error (rc = " + std::to_string(rc) + ") at '" + - input + "'"); + input.to_string() + "'"); logOffset(ruleMessage, offset, input.size()); } res = true; diff --git a/src/operators/validate_url_encoding.h b/src/operators/validate_url_encoding.h index 3f0498dc..b7a5dc16 100644 --- a/src/operators/validate_url_encoding.h +++ b/src/operators/validate_url_encoding.h @@ -31,8 +31,9 @@ class ValidateUrlEncoding : public Operator { ValidateUrlEncoding() : Operator("ValidateUrlEncoding") { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; static int validate_url_encoding(const char *input, uint64_t input_length, diff --git a/src/operators/validate_utf8_encoding.cc b/src/operators/validate_utf8_encoding.cc index ec5ac90a..8952ae57 100644 --- a/src/operators/validate_utf8_encoding.cc +++ b/src/operators/validate_utf8_encoding.cc @@ -113,8 +113,10 @@ int ValidateUtf8Encoding::detect_utf8_character( return unicode_len; } -bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, RuleMessage *ruleMessage) { +bool ValidateUtf8Encoding::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { unsigned int i, bytes_left; const char *str_c = str.c_str(); @@ -128,7 +130,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "not enough bytes in character " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); } return true; @@ -137,7 +139,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "invalid byte value in character " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -147,7 +149,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "overlong character detected " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -157,7 +159,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "use of restricted character " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -166,7 +168,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r case UNICODE_ERROR_DECODING_ERROR : if (transaction) { ms_dbg_a(transaction, 8, "Error validating UTF-8 decoding " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -177,7 +179,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (rc <= 0) { if (transaction) { ms_dbg_a(transaction, 8, "Internal error during UTF-8 validation " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } diff --git a/src/operators/validate_utf8_encoding.h b/src/operators/validate_utf8_encoding.h index a7d63c83..0f695c22 100644 --- a/src/operators/validate_utf8_encoding.h +++ b/src/operators/validate_utf8_encoding.h @@ -38,8 +38,9 @@ class ValidateUtf8Encoding : public Operator { ValidateUtf8Encoding() : Operator("ValidateUtf8Encoding") { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; static int detect_utf8_character(const unsigned char *p_read, diff --git a/src/operators/verify_cc.cc b/src/operators/verify_cc.cc index 0c6b4968..45b1e951 100644 --- a/src/operators/verify_cc.cc +++ b/src/operators/verify_cc.cc @@ -119,8 +119,10 @@ bool VerifyCC::init(const std::string ¶m2, std::string *error) { } -bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& i, RuleMessage *ruleMessage) { +bool VerifyCC::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &i, + RuleMessage *ruleMessage) { int offset = 0; int target_length = i.length(); @@ -139,18 +141,18 @@ bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule, return false; } if (ret > 0) { - match = std::string(i, ovector[0], ovector[1] - ovector[0]); + match = std::string(i.to_string(), ovector[0], ovector[1] - ovector[0]); int is_cc = luhnVerify(match.c_str(), match.size()); if (is_cc) { - if (t) { + if (transaction) { if (rule && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(match)); - ms_dbg_a(t, 7, "Added VerifyCC match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added VerifyCC match TX.0: " + \ std::string(match)); } - ms_dbg_a(t, 9, "CC# match \"" + m_param + - "\" at " + i + ". [offset " + + ms_dbg_a(transaction, 9, "CC# match \"" + m_param + + "\" at " + i.to_string() + ". [offset " + std::to_string(offset) + "]"); } return true; diff --git a/src/operators/verify_cc.h b/src/operators/verify_cc.h index 7095cbc8..d4cdf185 100644 --- a/src/operators/verify_cc.h +++ b/src/operators/verify_cc.h @@ -35,10 +35,13 @@ class VerifyCC : public Operator { m_pce(NULL) { } ~VerifyCC(); - bool evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, - RuleMessage *ruleMessage) override; bool init(const std::string ¶m, std::string *error) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + private: pcre *m_pc; pcre_extra *m_pce; diff --git a/src/operators/verify_cpf.cc b/src/operators/verify_cpf.cc index 3454dbab..922d6223 100644 --- a/src/operators/verify_cpf.cc +++ b/src/operators/verify_cpf.cc @@ -110,8 +110,10 @@ bool VerifyCPF::verify(const char *cpfnumber, int len) { } -bool VerifyCPF::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, RuleMessage *ruleMessage) { +bool VerifyCPF::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { std::list matches; bool is_cpf = false; int i; @@ -121,15 +123,15 @@ bool VerifyCPF::evaluate(Transaction *t, RuleWithActions *rule, } for (i = 0; i < input.size() - 1 && is_cpf == false; i++) { - matches = m_re->searchAll(input.substr(i, input.size())); + matches = m_re->searchAll(input.substr(i, input.size()).to_string()); for (const auto & m : matches) { is_cpf = verify(m.str().c_str(), m.str().size()); if (is_cpf) { logOffset(ruleMessage, m.offset(), m.str().size()); - if (rule && t && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + if (rule && transaction && rule->hasCaptureAction()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", m.str()); - ms_dbg_a(t, 7, "Added VerifyCPF match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added VerifyCPF match TX.0: " + \ m.str()); } diff --git a/src/operators/verify_cpf.h b/src/operators/verify_cpf.h index e15e74c4..9ee96643 100644 --- a/src/operators/verify_cpf.h +++ b/src/operators/verify_cpf.h @@ -46,8 +46,9 @@ class VerifyCPF : public Operator { bool operator=(const VerifyCPF &a) = delete; VerifyCPF(const VerifyCPF &a) = delete; - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; bool verify(const char *ssnumber, int len); diff --git a/src/operators/verify_ssn.cc b/src/operators/verify_ssn.cc index fae46828..f58d8d27 100644 --- a/src/operators/verify_ssn.cc +++ b/src/operators/verify_ssn.cc @@ -112,8 +112,10 @@ invalid: } -bool VerifySSN::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, RuleMessage *ruleMessage) { +bool VerifySSN::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { std::list matches; bool is_ssn = false; int i; @@ -123,15 +125,15 @@ bool VerifySSN::evaluate(Transaction *t, RuleWithActions *rule, } for (i = 0; i < input.size() - 1 && is_ssn == false; i++) { - matches = m_re->searchAll(input.substr(i, input.size())); + matches = m_re->searchAll(input.substr(i, input.size()).to_string()); for (const auto & j : matches) { is_ssn = verify(j.str().c_str(), j.str().size()); if (is_ssn) { logOffset(ruleMessage, j.offset(), j.str().size()); - if (rule && t && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + if (rule && transaction && rule->hasCaptureAction()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", j.str()); - ms_dbg_a(t, 7, "Added VerifySSN match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added VerifySSN match TX.0: " + \ j.str()); } diff --git a/src/operators/verify_ssn.h b/src/operators/verify_ssn.h index ef38cad3..a1c6b780 100644 --- a/src/operators/verify_ssn.h +++ b/src/operators/verify_ssn.h @@ -46,8 +46,9 @@ class VerifySSN : public Operator { bool operator=(const VerifySSN &a) = delete; VerifySSN(const VerifySSN &a) = delete; - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; diff --git a/src/operators/verify_svnr.cc b/src/operators/verify_svnr.cc index 8a444ac1..8f906b3c 100644 --- a/src/operators/verify_svnr.cc +++ b/src/operators/verify_svnr.cc @@ -78,8 +78,10 @@ bool VerifySVNR::verify(const char *svnrnumber, int len) { } -bool VerifySVNR::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, RuleMessage* ruleMessage) { +bool VerifySVNR::evaluate(Transaction *t, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage* ruleMessage) { std::list matches; bool is_svnr = false; int i; @@ -89,7 +91,7 @@ bool VerifySVNR::evaluate(Transaction *t, RuleWithActions *rule, } for (i = 0; i < input.size() - 1 && is_svnr == false; i++) { - matches = m_re->searchAll(input.substr(i, input.size())); + matches = m_re->searchAll(input.substr(i, input.size()).to_string()); for (const auto & j : matches) { is_svnr = verify(j.str().c_str(), j.str().size()); diff --git a/src/operators/verify_svnr.h b/src/operators/verify_svnr.h index 898bee79..b5ba9243 100644 --- a/src/operators/verify_svnr.h +++ b/src/operators/verify_svnr.h @@ -32,8 +32,9 @@ class VerifySVNR : public Operator { bool operator=(const VerifySVNR &a) = delete; VerifySVNR(const VerifySVNR &a) = delete; - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, RuleMessage *ruleMessage) override; bool verify(const char *ssnumber, int len); diff --git a/src/operators/within.cc b/src/operators/within.cc index a4ffc655..346243e1 100644 --- a/src/operators/within.cc +++ b/src/operators/within.cc @@ -24,8 +24,10 @@ namespace modsecurity { namespace operators { -bool Within::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, RuleMessage *ruleMessage) { +bool Within::evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { bool res = false; size_t pos = 0; std::string paramTarget(m_string->evaluate(transaction)); @@ -34,7 +36,7 @@ bool Within::evaluate(Transaction *transaction, RuleWithActions *rule, return true; } - pos = paramTarget.find(str); + pos = paramTarget.find(str.c_str()); res = pos != std::string::npos; if (res) { logOffset(ruleMessage, pos, str.size()); diff --git a/src/operators/within.h b/src/operators/within.h index b9921a73..a6bc5d31 100644 --- a/src/operators/within.h +++ b/src/operators/within.h @@ -33,8 +33,11 @@ class Within : public Operator { : Operator("Within", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, RuleMessage *ruleMessage) override; + + bool evaluate(Transaction *transaction, + RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 5ba8fa19..cb6667d2 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -41,6 +41,7 @@ #include "src/actions/block.h" #include "src/variables/variable.h" #include "src/rule_with_operator.h" +#include "modsecurity/string_view.hpp" namespace modsecurity { @@ -68,8 +69,9 @@ RuleWithOperator::~RuleWithOperator() { } -void RuleWithOperator::updateMatchedVars(Transaction *trans, const std::string &key, - const std::string &value) { +void RuleWithOperator::updateMatchedVars(Transaction *trans, + const std::string &key, + const bpstd::string_view &value) { ms_dbg_a(trans, 9, "Matched vars updated."); trans->m_variableMatchedVar.set(value, trans->m_variableOffset); trans->m_variableMatchedVarName.set(key, trans->m_variableOffset); @@ -88,9 +90,9 @@ void RuleWithOperator::cleanMatchedVars(Transaction *trans) { } - -bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string &key, - std::string value) { +bool RuleWithOperator::executeOperatorAt(Transaction *trans, + const std::string &key, + const bpstd::string_view &value) { #if MSC_EXEC_CLOCK_ENABLED clock_t begin = clock(); clock_t end; @@ -98,16 +100,13 @@ bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string & #endif bool ret; - ms_dbg_a(trans, 9, "Target value: \"" + utils::string::limitTo(80, - utils::string::toHexIfNeeded(value)) \ + ms_dbg_a(trans, 9, "Target value: \"" \ + + utils::string::limitTo(80, + utils::string::toHexIfNeeded(value.to_string())) \ + "\" (Variable: " + key + ")"); ret = m_operator->evaluateInternal(trans, this, value, trans->messageGetLast()); - if (ret == false) { - return false; - } - #if MSC_EXEC_CLOCK_ENABLED end = clock(); elapsed_s = static_cast(end - begin) / CLOCKS_PER_SEC; @@ -302,10 +301,9 @@ bool RuleWithOperator::evaluate(Transaction *trans) { while (iter != transformationsResults.end()) { bool ret; auto &valueTemp = *iter; - // FIXME: this copy is not necessary. - std::string *valueAfterTrans = new std::string(valueTemp.getAfter()->c_str(), valueTemp.getAfter()->size()); + bpstd::string_view view = *valueTemp.getAfter(); - ret = executeOperatorAt(trans, key, *valueAfterTrans); + ret = executeOperatorAt(trans, key, view); if (ret == true) { trans->messageGetLast()->m_match = m_operator->resolveMatchMessage(trans, @@ -330,12 +328,12 @@ bool RuleWithOperator::evaluate(Transaction *trans) { iter2++; } - updateMatchedVars(trans, key, *valueAfterTrans); + updateMatchedVars(trans, key, view); executeActionsIndependentOfChainedRuleResult(trans); globalRet = true; } - delete valueAfterTrans; + iter++; } delete v; diff --git a/src/rule_with_operator.h b/src/rule_with_operator.h index e69339af..f9990a50 100644 --- a/src/rule_with_operator.h +++ b/src/rule_with_operator.h @@ -32,6 +32,7 @@ #include "src/rule_with_actions.h" #include "src/variables/variable.h" #include "src/operators/operator.h" +#include "modsecurity/string_view.hpp" #ifdef __cplusplus @@ -61,11 +62,14 @@ class RuleWithOperator : public RuleWithActions { inline void getFinalVars(variables::Variables *vars, variables::Variables *eclusion, Transaction *trans); - bool executeOperatorAt(Transaction *trasn, const std::string &key, - std::string value); + bool executeOperatorAt(Transaction *transaction, + const std::string &key, + const bpstd::string_view &value); + + static void updateMatchedVars(Transaction *transaction, + const std::string &key, + const bpstd::string_view &value); - static void updateMatchedVars(Transaction *trasn, const std::string &key, - const std::string &value); static void cleanMatchedVars(Transaction *trasn); diff --git a/test/cppcheck_suppressions.txt b/test/cppcheck_suppressions.txt index fde3545a..de6b1b66 100644 --- a/test/cppcheck_suppressions.txt +++ b/test/cppcheck_suppressions.txt @@ -19,6 +19,12 @@ *:others/mbedtls/sha1.c +// +// 3rd party string view +// +*:headers/modsecurity/string_view.hpp + + // // Code imported from ModSecurity v2... // @@ -30,11 +36,10 @@ invalidScanfArgType_int:src/rules_set_properties.cc:102 redundantAssignment:src/operators/pm.cc:94 - // // ModSecurity v3 code... // -unmatchedSuppression:src/utils/geo_lookup.cc:82 +functionStatic:src/operators/geo_lookup.h:39 useInitializationList:src/utils/shared_files.h:87 unmatchedSuppression:src/utils/msc_tree.cc functionStatic:headers/modsecurity/transaction.h:455 @@ -54,8 +59,8 @@ syntaxError:src/transaction.cc:62 noConstructor:src/variables/variable.h:152 duplicateBranch:src/request_body_processor/multipart.cc:93 danglingTempReference:src/modsecurity.cc:206 -knownConditionTrueFalse:src/operators/validate_url_encoding.cc:77 -knownConditionTrueFalse:src/operators/verify_svnr.cc:88 +knownConditionTrueFalse:src/operators/validate_url_encoding.cc:79 +knownConditionTrueFalse:src/operators/verify_svnr.cc:90 noConstructor:src/actions/rule_id.h:33 functionStatic:src/actions/rule_id.h:35