From 39848e5564398575526dc574696acab1ef2a4e29 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 27 Mar 2024 11:45:05 +0100 Subject: [PATCH 01/75] Fix memleak in regression.cc --- test/regression/regression.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/regression/regression.cc b/test/regression/regression.cc index 6343c9e1..1a6b7646 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -476,7 +476,9 @@ int main(int argc, char **argv) { std::string ver(MODSECURITY_VERSION); std::string envvar("MODSECURITY=ModSecurity " + ver + " regression tests"); - putenv(strdup(envvar.c_str())); + char *envvarptr = strdup(envvar.c_str()); + + putenv(envvarptr); #ifndef NO_LOGS int test_number = 0; #endif @@ -536,6 +538,9 @@ int main(int argc, char **argv) { if (test.m_count_all) { std::cout << std::to_string(keyList.size()) << std::endl; + if (envvarptr != nullptr) { + free(envvarptr); + } exit(0); } @@ -606,5 +611,9 @@ int main(int argc, char **argv) { } #endif + if (envvarptr != nullptr) { + free(envvarptr); + } + return 0; } From 5b2404e44d8afbd979227a5fa2acb69622f6d694 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 27 Mar 2024 11:45:36 +0100 Subject: [PATCH 02/75] Fix memleak in rules-check.cc --- tools/rules-check/rules-check.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/rules-check/rules-check.cc b/tools/rules-check/rules-check.cc index f59439ee..b1b974a4 100644 --- a/tools/rules-check/rules-check.cc +++ b/tools/rules-check/rules-check.cc @@ -41,6 +41,7 @@ int main(int argc, char **argv) { if (*args == NULL) { print_help(argv[0]); + delete rules; return 0; } @@ -50,6 +51,7 @@ int main(int argc, char **argv) { const char *arg = *args; std::string err; int r; + bool need_free = false; if (argFull.empty() == false) { if (arg[strlen(arg)-1] == '\"') { @@ -72,6 +74,7 @@ int main(int argc, char **argv) { if (argFull.empty() == false) { arg = strdup(argFull.c_str()); + need_free = true; argFull.clear(); } @@ -81,6 +84,9 @@ int main(int argc, char **argv) { } else { r = rules->load(arg); } + if(need_free == true && arg != nullptr) { + free((void*)arg); + } if (r < 0) { err.assign(rules->m_parserError.str()); rules->m_parserError.str(""); From 4085ff553624121d6cd76d20064394e4d6d21c1a Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 27 Mar 2024 13:14:11 +0100 Subject: [PATCH 03/75] Replace putenv by setenv --- test/regression/regression.cc | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/test/regression/regression.cc b/test/regression/regression.cc index 1a6b7646..56eb43c8 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -474,11 +474,9 @@ int main(int argc, char **argv) { ModSecurityTest test; std::string ver(MODSECURITY_VERSION); - std::string envvar("MODSECURITY=ModSecurity " + ver + " regression tests"); + std::string envvar("ModSecurity " + ver + " regression tests"); - char *envvarptr = strdup(envvar.c_str()); - - putenv(envvarptr); + setenv("MODSECURITY", envvar.c_str(), 1); #ifndef NO_LOGS int test_number = 0; #endif @@ -538,9 +536,6 @@ int main(int argc, char **argv) { if (test.m_count_all) { std::cout << std::to_string(keyList.size()) << std::endl; - if (envvarptr != nullptr) { - free(envvarptr); - } exit(0); } @@ -611,9 +606,6 @@ int main(int argc, char **argv) { } #endif - if (envvarptr != nullptr) { - free(envvarptr); - } return 0; } From ca7c0ae0b94b0daad932aef25fa0fc0e99ef64dd Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 27 Mar 2024 16:19:38 +0100 Subject: [PATCH 04/75] Code refactorization --- tools/rules-check/rules-check.cc | 50 +++++++++----------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/tools/rules-check/rules-check.cc b/tools/rules-check/rules-check.cc index b1b974a4..9061f9f1 100644 --- a/tools/rules-check/rules-check.cc +++ b/tools/rules-check/rules-check.cc @@ -32,61 +32,39 @@ void print_help(const char *name) { int main(int argc, char **argv) { - modsecurity::RulesSet *rules; + std::unique_ptr rules (new modsecurity::RulesSet()); char **args = argv; - rules = new modsecurity::RulesSet(); int ret = 0; args++; if (*args == NULL) { print_help(argv[0]); - delete rules; return 0; } while (*args != NULL) { struct stat buffer; - std::string argFull(""); - const char *arg = *args; + std::string arg = (*args); std::string err; int r; - bool need_free = false; - if (argFull.empty() == false) { - if (arg[strlen(arg)-1] == '\"') { - argFull.append(arg, strlen(arg)-1); - goto next; - } else { - argFull.append(arg); - goto next; - } - } + // strip arg from leading and trailing '"' chars + arg.erase(arg.find_last_not_of('\"')+1); + arg.erase(0, arg.find_first_not_of('\"')); - if (arg[0] == '\"' && argFull.empty() == true) { - if (arg[strlen(arg)-1] == '\"') { - argFull.append(arg+1, strlen(arg) - 2); - } else { - argFull.append(arg+1); - goto next; - } - } - - if (argFull.empty() == false) { - arg = strdup(argFull.c_str()); - need_free = true; - argFull.clear(); + if (arg.empty() == true) { + args++; + continue; } std::cout << " : " << arg << " -- "; - if (stat(arg, &buffer) == 0) { - r = rules->loadFromUri(arg); + if (stat(arg.c_str(), &buffer) == 0) { + r = rules->loadFromUri(arg.c_str()); } else { - r = rules->load(arg); - } - if(need_free == true && arg != nullptr) { - free((void*)arg); + r = rules->load(arg.c_str()); } + if (r < 0) { err.assign(rules->m_parserError.str()); rules->m_parserError.str(""); @@ -97,12 +75,10 @@ int main(int argc, char **argv) { if (err.empty() == false) { std::cerr << " " << err << std::endl; } -next: + args++; } - delete rules; - if (ret < 0) { std::cout << "Test failed." << std::endl; } else { From 1b6b63161706e21511a536ac8ba740fcc475c418 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 27 Mar 2024 16:33:05 +0100 Subject: [PATCH 05/75] Use make_unique to create unique ptr --- tools/rules-check/rules-check.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rules-check/rules-check.cc b/tools/rules-check/rules-check.cc index 9061f9f1..f494d0c3 100644 --- a/tools/rules-check/rules-check.cc +++ b/tools/rules-check/rules-check.cc @@ -32,7 +32,7 @@ void print_help(const char *name) { int main(int argc, char **argv) { - std::unique_ptr rules (new modsecurity::RulesSet()); + std::unique_ptr rules = std::make_unique(); char **args = argv; int ret = 0; @@ -45,7 +45,7 @@ int main(int argc, char **argv) { while (*args != NULL) { struct stat buffer; - std::string arg = (*args); + std::string arg = *args; std::string err; int r; From cdb6b839e1de54ce126a2cc8e97a9f2c2846b5a9 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 27 Mar 2024 16:39:32 +0100 Subject: [PATCH 06/75] Replaced variable type to 'auto' --- tools/rules-check/rules-check.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rules-check/rules-check.cc b/tools/rules-check/rules-check.cc index f494d0c3..48cc465a 100644 --- a/tools/rules-check/rules-check.cc +++ b/tools/rules-check/rules-check.cc @@ -32,7 +32,7 @@ void print_help(const char *name) { int main(int argc, char **argv) { - std::unique_ptr rules = std::make_unique(); + auto rules = std::make_unique(); char **args = argv; int ret = 0; From b4659959cd2fe9fa38cf95e4065daf06c24a3c59 Mon Sep 17 00:00:00 2001 From: gberkes Date: Sun, 4 Aug 2024 22:04:07 +0200 Subject: [PATCH 07/75] Refactor: Ensure safe error handling by removing isolated throw; statements. - SonarCloud analysis identified standalone `throw;` calls without accompanying `try-catch` blocks, used inconsistently as placeholders or for premature termination under specific conditions. - Removed these `throw;` instances to prevent potential runtime issues in future development phases, where such configurations might inadvertently be created. - Introduced `assert` statements as a more appropriate mechanism for asserting preconditions in the affected class member functions, ensuring clearer intent and safer code behavior during development. - Refactor action_kind processing to use switch() instead of if-else chains; add assertion in default case. - Fix SonarCloud issue: Make this variable a const reference. https://sonarcloud.io/project/issues?resolved=false&pullRequest=3104&id=owasp-modsecurity_ModSecurity&open=AY8Vpgy4f6U6E7VKL4Cn --- headers/modsecurity/transaction.h | 8 ++- src/rule_with_actions.cc | 83 +++++++++++++++++-------------- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 9caace2c..e35ed6eb 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -14,6 +14,7 @@ */ #ifdef __cplusplus +#include #include #include #include @@ -307,11 +308,8 @@ class TransactionSecMarkerManagement { } std::shared_ptr getCurrentMarker() const { - if (m_marker) { - return m_marker; - } else { - throw; // cppcheck-suppress rethrowNoCurrentException - } + assert((m_marker != nullptr) && "You might have forgotten to call and evaluate isInsideAMarker() before calling getCurrentMarker()."); + return m_marker; } void removeMarker() { diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index 5ae7d407..7314b5c8 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -86,45 +87,51 @@ RuleWithActions::RuleWithActions( if (actions) { for (Action *a : *actions) { - if (a->action_kind == Action::ConfigurationKind) { - a->evaluate(this, NULL); - delete a; - - } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) { - if (dynamic_cast(a)) { - m_containsCaptureAction = true; + switch (a->action_kind) { + case Action::ConfigurationKind: + a->evaluate(this, NULL); delete a; - } else if (dynamic_cast(a)) { - m_containsMultiMatchAction = true; - delete a; - } else if (dynamic_cast(a)) { - m_severity = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_logData = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_msg = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_actionsSetVar.push_back( - dynamic_cast(a)); - } else if (dynamic_cast(a)) { - m_actionsTag.push_back(dynamic_cast(a)); - } else if (dynamic_cast(a)) { - m_actionsRuntimePos.push_back(a); - m_containsStaticBlockAction = true; - } else if (a->isDisruptive() == true) { - if (m_disruptiveAction != nullptr) { - delete m_disruptiveAction; - m_disruptiveAction = nullptr; + break; + case Action::RunTimeOnlyIfMatchKind: + if (dynamic_cast(a)) { + m_containsCaptureAction = true; + delete a; + } else if (dynamic_cast(a)) { + m_containsMultiMatchAction = true; + delete a; + } else if (dynamic_cast(a)) { + m_severity = dynamic_cast(a); + } else if (dynamic_cast(a)) { + m_logData = dynamic_cast(a); + } else if (dynamic_cast(a)) { + m_msg = dynamic_cast(a); + } else if (dynamic_cast(a)) { + m_actionsSetVar.push_back( + dynamic_cast(a)); + } else if (dynamic_cast(a)) { + m_actionsTag.push_back(dynamic_cast(a)); + } else if (dynamic_cast(a)) { + m_actionsRuntimePos.push_back(a); + m_containsStaticBlockAction = true; + } else if (a->isDisruptive() == true) { + if (m_disruptiveAction != nullptr) { + delete m_disruptiveAction; + m_disruptiveAction = nullptr; + } + m_disruptiveAction = a; + } else { + m_actionsRuntimePos.push_back(a); } - m_disruptiveAction = a; - } else { - m_actionsRuntimePos.push_back(a); - } - } else { - delete a; - std::cout << "General failure, action: " << a->m_name; - std::cout << " has an unknown type." << std::endl; - throw; // cppcheck-suppress rethrowNoCurrentException + break; + default: + std::cout << "General failure, action: " << a->m_name; + std::cout << " has an unknown type." << std::endl; + delete a; + #ifdef NDEBUG + break; + #else + assert(false); + #endif } } delete actions; @@ -239,7 +246,7 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, bool containsBlock, std::shared_ptr ruleMessage) { bool disruptiveAlreadyExecuted = false; - for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) { // cppcheck-suppress ctunullpointer + for (const auto &a : trans->m_rules->m_defaultActions[getPhase()]) { // cppcheck-suppress ctunullpointer if (a.get()->action_kind != actions::Action::RunTimeOnlyIfMatchKind) { continue; } From 053e3b526655b57b4b2007726ad50e690f0014b8 Mon Sep 17 00:00:00 2001 From: gberkes Date: Sun, 4 Aug 2024 22:13:58 +0200 Subject: [PATCH 08/75] Document the usage and the importance of assertions. --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 36201735..704967d6 100644 --- a/README.md +++ b/README.md @@ -236,10 +236,16 @@ CFLAGS to disable the compilation optimization parameters: ```shell $ export CFLAGS="-g -O0" $ ./build.sh -$ ./configure +$ ./configure --enable-assertions=yes $ make $ sudo make install ``` +"Assertions allow us to document assumptions and to spot violations early in the +development process. What is more, assertions allow us to spot violations with a +minimum of effort." https://dl.acm.org/doi/pdf/10.1145/240964.240969 + +It is recommended to use assertions where applicable, and to enable them with +'--enable-assertions=yes' during the testing and debugging workflow. ### Benchmarking From d47185d7710bdb8310cd12197eaebd1274b7a386 Mon Sep 17 00:00:00 2001 From: gberkes Date: Sun, 4 Aug 2024 22:47:15 +0200 Subject: [PATCH 09/75] Build System: Introduce Configurable Assertion Handling Implemented a new configuration option --enable-assertions=[yes|no] within config.ac, enabling controlled inclusion of -DNDEBUG in CPPFLAGS. The default setting suppresses assertions (by adding -DNDEBUG to CPPFLAGS), preserving the original behavior. This enhancement allows for the optional enabling of assertions during development or debugging by setting --enable-assertions=yes, thereby excluding -DNDEBUG from CPPFLAGS. --- .github/workflows/ci.yml | 6 +++--- configure.ac | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d745ba44..d1fe4cbb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,8 @@ jobs: matrix: os: [ubuntu-22.04] platform: - - {label: "x64", arch: "amd64", configure: ""} - - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32"} + - {label: "x64", arch: "amd64", configure: "--enable-assertions=yes"} + - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS= -m32--enable-assertions=yes"} compiler: - {label: "gcc", cc: "gcc", cxx: "g++"} - {label: "clang", cc: "clang", cxx: "clang++"} @@ -112,7 +112,7 @@ jobs: - name: build.sh run: ./build.sh - name: configure - run: ./configure ${{ matrix.configure.opt }} + run: ./configure ${{ matrix.configure.opt }} --enable-assertions=yes - uses: ammaraskar/gcc-problem-matcher@master - name: make run: make -j `sysctl -n hw.logicalcpu` diff --git a/configure.ac b/configure.ac index f69c5c61..d8943164 100644 --- a/configure.ac +++ b/configure.ac @@ -248,6 +248,17 @@ AC_SUBST([MSC_VERSION]) MSC_GIT_VERSION=msc_version_git AC_SUBST([MSC_GIT_VERSION]) +AC_ARG_ENABLE(assertions, + [AS_HELP_STRING([--enable-assertions],[Turn on assertions feature: undefine NDEBUG])], + + [case "${enableval}" in + yes) assertions=true ;; + no) assertions=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-assertions) ;; + esac], + + [assertions=false] + ) AC_ARG_ENABLE(debug-logs, [AS_HELP_STRING([--disable-debug-logs],[Turn off the SecDebugLog feature])], @@ -377,6 +388,14 @@ if test "$aflFuzzer" == "true"; then GLOBAL_CPPFLAGS="$GLOBAL_CPPFLAGS $FUZZ_CPPCFLAGS" $buildExamples = false fi + +case $assertions in + false) ASSERTIONS_CPPCFLAGS="-DNDEBUG" ;; + true) ASSERTIONS_CPPCFLAGS="-UNDEBUG" ;; + *) AC_MSG_ERROR(bad value ${assertions} for assertions) ;; +esac +GLOBAL_CPPFLAGS="$GLOBAL_CPPFLAGS $ASSERTIONS_CPPCFLAGS" + AC_SUBST(GLOBAL_LDADD) AC_SUBST(GLOBAL_CPPFLAGS) @@ -613,6 +632,11 @@ if test $buildTestUtilities = true; then else echo " + Test Utilities ....disabled" fi +if test $assertions = true; then + echo " + Assertions ....enabled" +else + echo " + Assertions ....disabled" +fi if test $debugLogs = true; then echo " + SecDebugLog ....enabled" else From dc3f80a15594222c798635c2452e4ae497f58bf1 Mon Sep 17 00:00:00 2001 From: gberkes Date: Sun, 4 Aug 2024 22:55:42 +0200 Subject: [PATCH 10/75] Fixed missing whitespace. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1fe4cbb..3c5fae6c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: os: [ubuntu-22.04] platform: - {label: "x64", arch: "amd64", configure: "--enable-assertions=yes"} - - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS= -m32--enable-assertions=yes"} + - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS= -m32 --enable-assertions=yes"} compiler: - {label: "gcc", cc: "gcc", cxx: "g++"} - {label: "clang", cc: "clang", cxx: "clang++"} From b4cb24327cfc4960b34ad2c95acce8fdf1a76402 Mon Sep 17 00:00:00 2001 From: gberkes Date: Sun, 4 Aug 2024 23:00:39 +0200 Subject: [PATCH 11/75] Fixed extra whitespace. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c5fae6c..04a99b00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: os: [ubuntu-22.04] platform: - {label: "x64", arch: "amd64", configure: "--enable-assertions=yes"} - - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS= -m32 --enable-assertions=yes"} + - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 --enable-assertions=yes"} compiler: - {label: "gcc", cc: "gcc", cxx: "g++"} - {label: "clang", cc: "clang", cxx: "clang++"} From 6cffa8f90416cd68044c533328e34e18d3f14be4 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Mon, 5 Aug 2024 14:30:26 +0200 Subject: [PATCH 12/75] Add _putenv() in case of WIN32 port instead of setenv() --- test/regression/regression.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/regression/regression.cc b/test/regression/regression.cc index 61df0838..a6ede61c 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -482,7 +482,12 @@ int main(int argc, char **argv) { std::string ver(MODSECURITY_VERSION); std::string envvar("ModSecurity " + ver + " regression tests"); +#ifndef WIN32 setenv("MODSECURITY", envvar.c_str(), 1); +#else + _putenv_s("MODSECURITY", envvar.c_str()); +#endif + #ifndef NO_LOGS int test_number = 0; #endif From e31ff7e60b290bbabdaa0dd514952aa34fb89b3d Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 20 May 2024 21:41:12 +0000 Subject: [PATCH 13/75] Build on macOS 14 arm64 --- .github/workflows/ci.yml | 8 ++++--- build/pcre.m4 | 49 ++++++++++++++++++++++++---------------- build/yajl.m4 | 23 +++++++++++++++++++ configure.ac | 4 ++-- 4 files changed, 60 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04a99b00..7e44db5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-12] + os: [macos-14] configure: - {label: "with parser generation", opt: "--enable-parser-generation" } - {label: "wo curl", opt: "--without-curl" } @@ -91,10 +91,12 @@ jobs: - {label: "with pcre2", opt: "--with-pcre2" } steps: - name: Setup Dependencies - # autoconf, curl, pcre2 not installed because they're already + # curl, pcre2 not installed because they're already # included in the image run: | - brew install automake \ + brew install autoconf \ + automake \ + libtool \ yajl \ lmdb \ lua \ diff --git a/build/pcre.m4 b/build/pcre.m4 index 5575797f..4d991232 100644 --- a/build/pcre.m4 +++ b/build/pcre.m4 @@ -27,30 +27,41 @@ else AC_MSG_CHECKING([for libpcre config script]) - for x in ${test_paths}; do - dnl # Determine if the script was specified and use it directly - if test ! -d "$x" -a -e "$x"; then - PCRE_CONFIG=$x - pcre_path="no" - break - fi + AC_CHECK_PROG([PCRE_CONFIG_IN_ENV], [pcre-config], [yes], [no]) - dnl # Try known config script names/locations - for PCRE_CONFIG in pcre-config; do - if test -e "${x}/bin/${PCRE_CONFIG}"; then - pcre_path="${x}/bin" + if test "$PCRE_CONFIG_IN_ENV" = "yes"; then + AC_MSG_NOTICE([pcre-config found in envinronment]) + + PCRE_CONFIG=pcre-config + pcre_path="no" + else + AC_MSG_NOTICE([pcre-config not found in environment. checking known paths]) + + for x in ${test_paths}; do + dnl # Determine if the script was specified and use it directly + if test ! -d "$x" -a -e "$x"; then + PCRE_CONFIG=$x + pcre_path="no" break - elif test -e "${x}/${PCRE_CONFIG}"; then - pcre_path="${x}" + fi + + dnl # Try known config script names/locations + for PCRE_CONFIG in pcre-config; do + if test -e "${x}/bin/${PCRE_CONFIG}"; then + pcre_path="${x}/bin" + break + elif test -e "${x}/${PCRE_CONFIG}"; then + pcre_path="${x}" + break + else + pcre_path="" + fi + done + if test -n "$pcre_path"; then break - else - pcre_path="" fi done - if test -n "$pcre_path"; then - break - fi - done + fi if test -n "${pcre_path}"; then if test "${pcre_path}" != "no"; then diff --git a/build/yajl.m4 b/build/yajl.m4 index dd695715..e050c084 100644 --- a/build/yajl.m4 +++ b/build/yajl.m4 @@ -78,6 +78,29 @@ else # fi fi +# FIX: if the include directory in CFLAGS ends with "include/yajl", +# remove the suffix "/yajl". the library header files are included +# using the prefix (for example, #include ), and +# this is even the case for the library itself (for example, +# yajl_tree.h includes yajl/yajl_common.h). + +new_cflags="" + +for flag in $YAJL_CFLAGS; do + case "$flag" in + -I*/include/yajl) + new_flag="${flag%/yajl}" + new_cflags="$new_cflags $new_flag" + ;; + *) + new_cflags="$new_cflags $flag" + ;; + esac +done + +YAJL_CFLAGS="$new_cflags" + + if test -z "${YAJL_LDADD}"; then if test -z "${YAJL_MANDATORY}"; then if test -z "${YAJL_DISABLED}"; then diff --git a/configure.ac b/configure.ac index d8943164..38699272 100644 --- a/configure.ac +++ b/configure.ac @@ -164,8 +164,8 @@ AC_CHECK_HEADERS([iostream]) AC_CHECK_HEADERS([sys/utsname.h]) -# ?? -LT_INIT([dlopen]) +# Initialize libtool +LT_INIT # Identify platform AC_CANONICAL_HOST From dab9bb6a11aa70667c27295f48109685b9a23490 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 3 May 2024 14:33:02 -0300 Subject: [PATCH 14/75] Added methods to free buffers allocated by ModSecurity APIs - The following methods are introduced to allow clients of libModSecurity that are not able to link and call the C/C++ standard library to be able to free the buffers allocated by libModSecurity. - msc_intervention_cleanup: Frees the buffers in a ModSecurityIntervention structure that have been allocated by calls to msc_intervention. - msc_rules_error_cleanup: Frees an error message buffer allocated by the msc_rules_xxx functions to detail the condition that triggered the error. --- examples/simple_example_using_c/test.c | 2 ++ headers/modsecurity/rules_set.h | 1 + headers/modsecurity/transaction.h | 3 +++ src/rules_set.cc | 15 +++++++++++++++ src/transaction.cc | 16 ++++++++++++++++ 5 files changed, 37 insertions(+) diff --git a/examples/simple_example_using_c/test.c b/examples/simple_example_using_c/test.c index c7ed91b2..0c60ad5c 100644 --- a/examples/simple_example_using_c/test.c +++ b/examples/simple_example_using_c/test.c @@ -68,6 +68,8 @@ int main (int argc, char **argv) msc_process_response_body(transaction); msc_process_logging(transaction); end: + if(error != NULL) + msc_rules_error_cleanup(error); msc_rules_cleanup(rules); msc_cleanup(modsec); diff --git a/headers/modsecurity/rules_set.h b/headers/modsecurity/rules_set.h index 4af55f40..c5616cc4 100644 --- a/headers/modsecurity/rules_set.h +++ b/headers/modsecurity/rules_set.h @@ -99,6 +99,7 @@ int msc_rules_add_remote(RulesSet *rules, const char *key, const char *uri, const char **error); int msc_rules_add_file(RulesSet *rules, const char *file, const char **error); int msc_rules_add(RulesSet *rules, const char *plain_rules, const char **error); +void msc_rules_error_cleanup(const char *error); int msc_rules_cleanup(RulesSet *rules); #ifdef __cplusplus diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index e35ed6eb..c5e8881f 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -723,6 +723,9 @@ void msc_transaction_cleanup(Transaction *transaction); /** @ingroup ModSecurity_C_API */ int msc_intervention(Transaction *transaction, ModSecurityIntervention *it); +/** @ingroup ModSecurity_C_API */ +void msc_intervention_cleanup(ModSecurityIntervention *it); + /** @ingroup ModSecurity_C_API */ int msc_process_logging(Transaction *transaction); diff --git a/src/rules_set.cc b/src/rules_set.cc index 883c78e1..025abe69 100644 --- a/src/rules_set.cc +++ b/src/rules_set.cc @@ -311,6 +311,21 @@ extern "C" int msc_rules_add(RulesSet *rules, const char *plain_rules, } +/** + * @name msc_rules_error_cleanup + * @brief Deallocates an error message buffer returned by a msc_rules_xxx function. + * + * This is a helper function to free the error message buffer allocated + * by a msc_rules_xxx function. + * + * @param error Error message pointer. + * + */ +extern "C" void msc_rules_error_cleanup(const char *error) { + free((void*) error); +} + + extern "C" int msc_rules_cleanup(RulesSet *rules) { delete rules; return true; diff --git a/src/transaction.cc b/src/transaction.cc index efd1cd1b..5826c264 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -2273,6 +2273,22 @@ extern "C" int msc_intervention(Transaction *transaction, } +/** + * @name msc_intervention_cleanup + * @brief Removes all the resources allocated by a given Intervention. + * + * This is a helper function to free any allocated buffers owned by the + * intervention. + * + * @param it ModSecurity intervention. + * + */ +extern "C" void msc_intervention_cleanup(ModSecurityIntervention *it) { + intervention::free(it); + intervention::clean(it); +} + + /** * @name msc_get_response_body * @brief Retrieve a buffer with the updated response body. From 0dce46062b5a3e6bc099ad43ff9e52966f95bb28 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 5 Aug 2024 10:39:40 -0700 Subject: [PATCH 15/75] Fixed potential memory leak when there is an intervention and log or url is set. --- test/benchmark/benchmark.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/benchmark/benchmark.cc b/test/benchmark/benchmark.cc index a1037a47..8b36d368 100644 --- a/test/benchmark/benchmark.cc +++ b/test/benchmark/benchmark.cc @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) { modsecurity::ModSecurity *modsec; modsecurity::RulesSet *rules; modsecurity::ModSecurityIntervention it; - modsecurity::intervention::reset(&it); + modsecurity::intervention::clean(&it); modsec = new modsecurity::ModSecurity(); modsec->setConnectorInformation("ModSecurity-benchmark v0.0.1-alpha" \ " (ModSecurity benchmark utility)"); @@ -167,6 +167,8 @@ int main(int argc, char *argv[]) { next_request: modsecTransaction->processLogging(); delete modsecTransaction; + modsecurity::intervention::free(&it); + modsecurity::intervention::clean(&it); } delete rules; From 4b5f719906f382a3318981126db19d775041c50a Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 5 Aug 2024 08:49:06 -0700 Subject: [PATCH 16/75] Fixed shared files deadlock in a multi-threaded Windows application - The shared files Windows implementation introduced in PR #3132 works in multi-process single-threaded contexts but it doesn't work correctly in single-process multi-threaded contexts. - The issue is that the LockFileEx Win32 function works on a per-handle basis. - In a multi-process context, each process will have called SharedFiles::add_new_handler when initializing the SharedFile and obtained a handle, and thus locking will work. - When running ModSecurity in a single process using multiple threads, the initialization of the SharedFile will happen once and the handle will be shared by all threads. Then, if two threads try to write to the same shared file concurrently, they may deadlock as one of them will lock the file (by calling LockFileEx) and then proceed to write to the file. If before writing to the file and unlocking it, another thread calls LockFileEx on the same handle, the attempt to write to the file will lock generating a deadlock. - The new implementation replaces usage of LockFileEx/UnlockFileEx with a named mutex to lock access to the shared file. - A named mutex is used to support multi-process scenarios. - The mutex name is generated using the filename to support multiple shared files (such as that for the debug and audit logs). - This assumes that both process will initialize the SharedFile instance using the same filename (which is expected as they'd be using the same configuration file) --- src/utils/shared_files.cc | 44 ++++++++++++++++++++++++++++++++------- src/utils/shared_files.h | 6 ++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/utils/shared_files.cc b/src/utils/shared_files.cc index df18022f..6982d0d6 100644 --- a/src/utils/shared_files.cc +++ b/src/utils/shared_files.cc @@ -17,8 +17,7 @@ #include #ifdef WIN32 -#include -#include +#include #endif @@ -34,7 +33,32 @@ SharedFiles::handlers_map::iterator SharedFiles::add_new_handler( return m_handlers.end(); } - return m_handlers.insert({ fileName, {fp, 0} }).first; +#ifdef WIN32 + // replace invalid characters for a Win32 named object + auto tmp = fileName; + std::replace(tmp.begin(), tmp.end(), '\\', '_'); + std::replace(tmp.begin(), tmp.end(), '/', '_'); + + // use named mutex for multi-process locking support + const auto mutexName = "Global\\ModSecurity_" + tmp; + + HANDLE hMutex = CreateMutex(NULL, FALSE, mutexName.c_str()); + if (hMutex == NULL) { + error->assign("Failed to create mutex for shared file: " + fileName); + fclose(fp); + return m_handlers.end(); + } +#endif + + auto handler = handler_info { + fp, +#ifdef WIN32 + hMutex, +#endif + 0 + }; + // cppcheck-suppress resourceLeak ; false positive, fp is closed in SharedFiles::close + return m_handlers.insert({ fileName, handler }).first; } @@ -69,6 +93,9 @@ void SharedFiles::close(const std::string& fileName) { if (it->second.cnt == 0) { fclose(it->second.fp); +#ifdef WIN32 + CloseHandle(it->second.hMutex); +#endif m_handlers.erase(it); } @@ -92,9 +119,11 @@ bool SharedFiles::write(const std::string& fileName, lock.l_type = F_WRLCK; fcntl(fileno(it->second.fp), F_SETLKW, &lock); #else - auto handle = reinterpret_cast(_get_osfhandle(fileno(it->second.fp))); - OVERLAPPED overlapped = { 0 }; - ::LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped); + DWORD dwWaitResult = WaitForSingleObject(it->second.hMutex, INFINITE); + if (dwWaitResult != WAIT_OBJECT_0) { + error->assign("couldn't lock shared file: " + fileName); + return false; + } #endif auto wrote = fwrite(msg.c_str(), 1, msg.size(), it->second.fp); @@ -109,8 +138,7 @@ bool SharedFiles::write(const std::string& fileName, lock.l_type = F_UNLCK; fcntl(fileno(it->second.fp), F_SETLKW, &lock); #else - overlapped = { 0 }; - ::UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped); + ::ReleaseMutex(it->second.hMutex); #endif return ret; diff --git a/src/utils/shared_files.h b/src/utils/shared_files.h index 4953eeff..fcc78c98 100644 --- a/src/utils/shared_files.h +++ b/src/utils/shared_files.h @@ -18,6 +18,9 @@ #include +#ifdef WIN32 +#include +#endif #include #include @@ -53,6 +56,9 @@ private: struct handler_info { FILE* fp; +#ifdef WIN32 + HANDLE hMutex; +#endif unsigned int cnt; }; From c947f5e40dd3428024a3a8b9c9174ee9c85fd150 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 5 Aug 2024 11:18:35 -0700 Subject: [PATCH 17/75] Do not assume ModSecurityIntervention argument to transaction::intervention has been initialized/cleaned - Keep m_it->disruptive value and use it as return value to guarantee that the value is correct. - If m_it->disruptive is false and the 'it' argument has not been initialized/cleaned, the function may incorrectly return a non-zero value. - When a disruptive intervention is being reported by the function, defensively initialize log & url to NULL if there's no such data to provide to the caller. - If the caller has not initialized/cleaned those fields in the 'it' argument, after returning from transaction::intervention, the user can safely read the log & url fields and in all scenarios they'll have valid values. --- src/transaction.cc | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/transaction.cc b/src/transaction.cc index 5826c264..a19ce88b 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -1469,16 +1469,24 @@ int Transaction::processLogging() { * @brief Check if ModSecurity has anything to ask to the server. * * Intervention can generate a log event and/or perform a disruptive action. + * + * If the return value is true, all fields in the ModSecurityIntervention + * parameter have been initialized and are safe to access. + * If the return value is false, no changes to the ModSecurityIntervention + * parameter have been made. * - * @param Pointer ModSecurityIntervention structure + * @param it Pointer to ModSecurityIntervention structure * @retval true A intervention should be made. * @retval false Nothing to be done. * */ bool Transaction::intervention(ModSecurityIntervention *it) { + const auto disruptive = m_it.disruptive; if (m_it.disruptive) { if (m_it.url) { it->url = strdup(m_it.url); + } else { + it->url = NULL; } it->disruptive = m_it.disruptive; it->status = m_it.status; @@ -1489,11 +1497,13 @@ bool Transaction::intervention(ModSecurityIntervention *it) { utils::string::replaceAll(&log, std::string("%d"), std::to_string(it->status)); it->log = strdup(log.c_str()); + } else { + it->log = NULL; } intervention::reset(&m_it); } - return it->disruptive; + return disruptive; } @@ -2260,11 +2270,16 @@ extern "C" void msc_transaction_cleanup(Transaction *transaction) { * * Intervention can generate a log event and/or perform a disruptive action. * - * @param transaction ModSecurity transaction. + * If the return value is not zero, all fields in the ModSecurityIntervention + * parameter have been initialized and are safe to access. + * If the return value is zero, no changes to the ModSecurityIntervention + * parameter have been made. * - * @return Pointer to ModSecurityIntervention structure - * @retval >0 A intervention should be made. - * @retval NULL Nothing to be done. + * @param transaction ModSecurity transaction. + * @param it Pointer to ModSecurityIntervention structure + * @returns If an intervention should be made + * @retval >0 A intervention should be made. + * @retval 0 Nothing to be done. * */ extern "C" int msc_intervention(Transaction *transaction, From 0b5493d4e73f29a5e4b08ec8488922d29b1450a3 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Tue, 6 Aug 2024 06:32:52 -0700 Subject: [PATCH 18/75] Minor performance improvements setting up intervention's log - Initialize `log` temporary value on construction instead of doing default initialization and then calling `append`. - Leverage `std::string_view` to replace `const std::string&` parameters in `utils::string::replaceAll` to avoid creating a `std::string` object (and associated allocation and copy) for the string literal`%d` --- src/transaction.cc | 5 ++--- src/utils/string.cc | 8 ++++---- src/utils/string.h | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/transaction.cc b/src/transaction.cc index a19ce88b..7dc8ba24 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -1492,9 +1492,8 @@ bool Transaction::intervention(ModSecurityIntervention *it) { it->status = m_it.status; if (m_it.log != NULL) { - std::string log(""); - log.append(m_it.log); - utils::string::replaceAll(&log, std::string("%d"), + std::string log(m_it.log); + utils::string::replaceAll(log, "%d", std::to_string(it->status)); it->log = strdup(log.c_str()); } else { diff --git a/src/utils/string.cc b/src/utils/string.cc index 8d9e08ff..276fd31f 100644 --- a/src/utils/string.cc +++ b/src/utils/string.cc @@ -254,11 +254,11 @@ unsigned char *c2x(unsigned what, unsigned char *where) { } -void replaceAll(std::string *str, const std::string& from, - const std::string& to) { +void replaceAll(std::string &str, std::string_view from, + std::string_view to) { size_t start_pos = 0; - while ((start_pos = str->find(from, start_pos)) != std::string::npos) { - str->replace(start_pos, from.length(), to); + while ((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); start_pos += to.length(); } } diff --git a/src/utils/string.h b/src/utils/string.h index 55ebc0bd..1cd63296 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -68,8 +68,8 @@ std::vector ssplit(std::string str, char delimiter); std::pair ssplit_pair(const std::string& str, char delimiter); std::vector split(std::string str, char delimiter); void chomp(std::string *str); -void replaceAll(std::string *str, const std::string& from, - const std::string& to); +void replaceAll(std::string &str, std::string_view from, + std::string_view to); std::string removeWhiteSpacesIfNeeded(std::string a); std::string parserSanitizer(std::string a); From c802b46b7e4fc719cb7e1f2d798f18dfe3391fd3 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Tue, 6 Aug 2024 14:29:17 -0700 Subject: [PATCH 19/75] Simplify parser error detection in testcase - After the GitHub macOS runner images were upgraded to macOS 14.6 (Sonoma), the test 'Include remote rules - failed download (Abort)' started failing because the error message reported by curl/OS is no longer 'HTTP response code said error'. --- test/test-cases/regression/config-secremoterules.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-cases/regression/config-secremoterules.json b/test/test-cases/regression/config-secremoterules.json index 017245c1..1ba3fd4b 100644 --- a/test/test-cases/regression/config-secremoterules.json +++ b/test/test-cases/regression/config-secremoterules.json @@ -46,7 +46,7 @@ "version_min":300000, "title":"Include remote rules - failed download (Abort)", "expected":{ - "parser_error": "Failed to download: HTTP response code said error" + "parser_error": "Failed to download" }, "rules":[ "SecRuleEngine On", From c46f470d6bb43534473ba85abb3663641f8c868f Mon Sep 17 00:00:00 2001 From: gberkes Date: Wed, 7 Aug 2024 10:39:06 +0200 Subject: [PATCH 20/75] Refactor: moved 3 #include directives to the top of the file. To aid code readability, all #include directives in a code file should be grouped together near the top. The only items that may precede an #include in a file are other preprocessor directives or comments. Reference: https://sonarcloud.io/project/issues?sinceLeakPeriod=true&issueStatuses=OPEN%2CCONFIRMED&id=owasp-modsecurity_ModSecurity&open=AY8-ffgqm_fzkWiCOtCs&tab=code Deleted some unnecessary trailing spaces as well. --- headers/modsecurity/modsecurity.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/headers/modsecurity/modsecurity.h b/headers/modsecurity/modsecurity.h index 192cd22e..d44ad248 100644 --- a/headers/modsecurity/modsecurity.h +++ b/headers/modsecurity/modsecurity.h @@ -38,10 +38,10 @@ * std::cout << "There is an intervention" << std::endl; * } * - * ... + * ... * * @endcode - * + * */ /** @@ -81,6 +81,11 @@ #endif +#include "modsecurity/intervention.h" +#include "modsecurity/transaction.h" +#include "modsecurity/debug_log.h" + + #ifndef HEADERS_MODSECURITY_MODSECURITY_H_ #define HEADERS_MODSECURITY_MODSECURITY_H_ @@ -160,7 +165,7 @@ namespace modsecurity { LoggingPhase, /** * Just a marking for the expected number of phases. - * + * */ NUMBER_OF_PHASES, }; @@ -170,11 +175,6 @@ namespace modsecurity { #endif - -#include "modsecurity/intervention.h" -#include "modsecurity/transaction.h" -#include "modsecurity/debug_log.h" - /** * TAG_NUM: * From ab78d4af79c1b6e2a4647ea1012b47cf7ecdd8ff Mon Sep 17 00:00:00 2001 From: gberkes Date: Wed, 7 Aug 2024 13:05:02 +0200 Subject: [PATCH 21/75] Refactor: used the init-statement to declare "pos" inside the if statement. C++17 introduced a construct to create and initialize a variable within the condition of if and switch statements, and C++20 added this construct to range-based for loops. Using this new feature simplifies common code patterns and helps in giving variables the right scope. Reference: https://sonarcloud.io/project/issues?open=AZDCieK2zGtqRpL2rnl-&id=owasp-modsecurity_ModSecurity --- src/variables/remote_user.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index 23bc6487..550294c7 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -56,8 +56,7 @@ void RemoteUser::evaluate(Transaction *transaction, base64 = Utils::Base64::decode(base64); - const auto pos = base64.find(":"); - if (pos != std::string::npos) { + if (const auto pos{base64.find(":")}; pos != std::string::npos) { transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos)); auto var = std::make_unique(&v->getKeyWithCollection(), From 35e825d6435dbef2c2de0daf6acc9faecbba5983 Mon Sep 17 00:00:00 2001 From: gberkes Date: Wed, 7 Aug 2024 17:55:30 +0200 Subject: [PATCH 22/75] Refactor: replaced 3 declarations with 3 structured binding declarations. This syntax is far more expressive and easier to understand than the old one. Refactor: flipped the conditions in "if (contains[Tag|Msg|Id]( ... " statements for clearer code. Refactor: moved "Variable *b" as an init-statement inside "if()" statements for stricter scope. Reference: https://sonarcloud.io/project/issues?open=AY8-ff1vm_fzkWiCOtCt&id=owasp-modsecurity_ModSecurity --- src/rule_with_operator.cc | 54 +++++++++++++++------------------------ 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 3a5ff385..0eb5ea30 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -133,45 +133,33 @@ bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string & void RuleWithOperator::getVariablesExceptions(Transaction *t, variables::Variables *exclusion, variables::Variables *addition) { - for (const auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_tag) { // cppcheck-suppress ctunullpointer - if (containsTag(*a.first.get(), t) == false) { - continue; - } - Variable *b = a.second.get(); - if (dynamic_cast(b)) { - exclusion->push_back( - dynamic_cast( - b)->m_base.get()); - } else { - addition->push_back(b); + for (const auto &[tag, v] : t->m_rules->m_exceptions.m_variable_update_target_by_tag) { // cppcheck-suppress ctunullpointer + if (containsTag(*tag.get(), t)) { + if (Variable *b{v.get()};dynamic_cast(b)) { + exclusion->push_back(dynamic_cast(b)->m_base.get()); + } else { + addition->push_back(b); + } } } - for (const auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_msg) { - if (containsMsg(*a.first.get(), t) == false) { - continue; - } - Variable *b = a.second.get(); - if (dynamic_cast(b)) { - exclusion->push_back( - dynamic_cast( - b)->m_base.get()); - } else { - addition->push_back(b); + for (const auto &[msg, v] : t->m_rules->m_exceptions.m_variable_update_target_by_msg) { + if (containsMsg(*msg.get(), t)) { + if (Variable *b{v.get()}; dynamic_cast(b)) { + exclusion->push_back(dynamic_cast(b)->m_base.get()); + } else { + addition->push_back(b); + } } } - for (const auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_id) { - if (m_ruleId != a.first) { - continue; - } - Variable *b = a.second.get(); - if (dynamic_cast(b)) { - exclusion->push_back( - dynamic_cast( - b)->m_base.get()); - } else { - addition->push_back(b); + for (const auto &[id, v] : t->m_rules->m_exceptions.m_variable_update_target_by_id) { + if (m_ruleId == id) { + if (Variable *b{v.get()};dynamic_cast(b)) { + exclusion->push_back(dynamic_cast(b)->m_base.get()); + } else { + addition->push_back(b); + } } } } From c50a397a87f79f076a778b3228957d7063eb444e Mon Sep 17 00:00:00 2001 From: gberkes Date: Wed, 7 Aug 2024 21:05:47 +0200 Subject: [PATCH 23/75] Suppress cppcheck false positive unassignedVariable warning. --- src/rule_with_operator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 0eb5ea30..d63129da 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -153,7 +153,7 @@ void RuleWithOperator::getVariablesExceptions(Transaction *t, } } - for (const auto &[id, v] : t->m_rules->m_exceptions.m_variable_update_target_by_id) { + for (const auto &[id, v] : t->m_rules->m_exceptions.m_variable_update_target_by_id) { // cppcheck-suppress unassignedVariable if (m_ruleId == id) { if (Variable *b{v.get()};dynamic_cast(b)) { exclusion->push_back(dynamic_cast(b)->m_base.get()); From cf643d6072b61e7c5ea2c1c14e9ca75a775a0f2c Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Thu, 8 Aug 2024 08:16:14 -0700 Subject: [PATCH 24/75] Avoid duplicate definition of --enable-assertions=yes configure flag on Unix builds - This configuration flag was introduced in commit d47185d in the context of PR #3207. - Moved to the configure step's 'run' command in order to be shared across configurations. - For the sake of reference, matrix.platform.configure should be used for configuration flags that are needed for a specific platform/architecture (which was the reason it was introduced in commit d9255d8, PR #3144). --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e44db5a..10ac5144 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,8 @@ jobs: matrix: os: [ubuntu-22.04] platform: - - {label: "x64", arch: "amd64", configure: "--enable-assertions=yes"} - - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 --enable-assertions=yes"} + - {label: "x64", arch: "amd64", configure: ""} + - {label: "x32", arch: "i386", configure: "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32"} compiler: - {label: "gcc", cc: "gcc", cxx: "g++"} - {label: "clang", cc: "clang", cxx: "clang++"} @@ -66,7 +66,7 @@ jobs: env: CC: ${{ matrix.compiler.cc }} CXX: ${{ matrix.compiler.cxx }} - run: ./configure ${{ matrix.platform.configure }} ${{ matrix.configure.opt }} + run: ./configure ${{ matrix.platform.configure }} ${{ matrix.configure.opt }} --enable-assertions=yes - uses: ammaraskar/gcc-problem-matcher@master - name: make run: make -j `nproc` From 59254fe3bde1cf27adfa169cb38cba3c9724d91f Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 24 May 2024 10:08:53 -0300 Subject: [PATCH 25/75] Simplifiy configuration to build libModSecurity with std C++17 - Leveraged autoconf again to check whether the C++ compiler supports the required standard version and build using it. - Replaced the outdaded `ax_cxx_compile_stdcxx_11.m4` macro with the latest version of `ax_cxx_compile_stdcxx` which supports C++17. - https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html - https://raw.githubusercontent.com/autoconf-archive/autoconf-archive/e4e5269db2764b9f53d759c24750ac6ca38e02ea/m4/ax_cxx_compile_stdcxx.m4 - This should also streamline updating to C++20 in the future. --- build/ax_cxx_compile_stdcxx.m4 | 1018 +++++++++++++++++ build/ax_cxx_compile_stdcxx_11.m4 | 171 --- configure.ac | 4 +- .../reading_logs_via_rule_message/Makefile.am | 1 - examples/reading_logs_with_offset/Makefile.am | 1 - examples/using_bodies_in_chunks/Makefile.am | 1 - src/Makefile.am | 1 - src/parser/Makefile.am | 1 - test/Makefile.am | 3 - test/benchmark/Makefile.am | 1 - test/fuzzer/Makefile.am | 1 - tools/rules-check/Makefile.am | 1 - 12 files changed, 1020 insertions(+), 184 deletions(-) create mode 100644 build/ax_cxx_compile_stdcxx.m4 delete mode 100644 build/ax_cxx_compile_stdcxx_11.m4 diff --git a/build/ax_cxx_compile_stdcxx.m4 b/build/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 00000000..8edf5152 --- /dev/null +++ b/build/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,1018 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for +# the respective C++ standard version. +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for no added switch, and then for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 18 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + dnl MSVC needs -std:c++NN for C++17 and later (default is C++14) + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do + if test x"$switch" = xMSVC; then + dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide + dnl with -std=c++17. We suffix the cache variable name with _MSVC to + dnl avoid this. + switch=-std:c++${alternative} + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC]) + else + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + fi + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +dnl Test body for checking C++17 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +#elif __cplusplus < 201103L && !defined _MSC_VER + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L && !defined _MSC_VER + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L && !defined _MSC_VER + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L && !defined _MSC_VER + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L && !defined _MSC_VER + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L && !defined _MSC_VER + +]]) diff --git a/build/ax_cxx_compile_stdcxx_11.m4 b/build/ax_cxx_compile_stdcxx_11.m4 deleted file mode 100644 index e76fd605..00000000 --- a/build/ax_cxx_compile_stdcxx_11.m4 +++ /dev/null @@ -1,171 +0,0 @@ -# ============================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html -# ============================================================================ -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the C++11 -# standard; if necessary, add switches to CXXFLAGS to enable support. -# -# The first argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. -# -# The second argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline C++11 support is required and that the macro -# should error out if no mode with that support is found. If specified -# 'optional', then configuration proceeds regardless, after defining -# HAVE_CXX11 if and only if a supporting mode is found. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik -# Copyright (c) 2012 Zack Weinberg -# Copyright (c) 2013 Roy Stogner -# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov -# Copyright (c) 2015 Paul Norman -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 12 - -m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - struct Base { - virtual void f() {} - }; - struct Child : public Base { - virtual void f() override {} - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); - - auto d = a; - auto l = [](){}; - // Prevent Clang error: unused variable 'l' [-Werror,-Wunused-variable] - struct use_l { use_l() { l(); } }; - - // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae - // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function because of this - namespace test_template_alias_sfinae { - struct foo {}; - - template - using member = typename T::member_type; - - template - void func(...) {} - - template - void func(member*) {} - - void test(); - - void test() { - func(0); - } - } - - // Check for C++11 attribute support - void noret [[noreturn]] () { throw 0; } -]]) - -AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl - m4_if([$1], [], [], - [$1], [ext], [], - [$1], [noext], [], - [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl - m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], - [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], - [$2], [optional], [ax_cxx_compile_cxx11_required=false], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])]) - AC_LANG_PUSH([C++])dnl - ac_success=no - AC_CACHE_CHECK(whether $CXX supports C++11 features by default, - ax_cv_cxx_compile_cxx11, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [ax_cv_cxx_compile_cxx11=yes], - [ax_cv_cxx_compile_cxx11=no])]) - if test x$ax_cv_cxx_compile_cxx11 = xyes; then - ac_success=yes - fi - - m4_if([$1], [noext], [], [dnl - if test x$ac_success = xno; then - for switch in -std=gnu++11 -std=gnu++0x; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, - $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) - if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" - ac_success=yes - break - fi - done - fi]) - - m4_if([$1], [ext], [], [dnl - if test x$ac_success = xno; then - dnl HP's aCC needs +std=c++11 according to: - dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf - for switch in -std=c++11 -std=c++0x +std=c++11; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, - $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) - if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" - ac_success=yes - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx11_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) - fi - else - if test x$ac_success = xno; then - HAVE_CXX11=0 - AC_MSG_NOTICE([No compiler with C++11 support was found]) - else - HAVE_CXX11=1 - AC_DEFINE(HAVE_CXX11,1, - [define if the compiler supports basic C++11 syntax]) - fi - - AC_SUBST(HAVE_CXX11) - fi -]) diff --git a/configure.ac b/configure.ac index 38699272..3a0fbb48 100644 --- a/configure.ac +++ b/configure.ac @@ -52,8 +52,8 @@ AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG -# Check if the compiler is c++17 compatible. -# AX_CXX_COMPILE_STDCXX_17(,mandatory) +# Set C++ standard version and check if compiler supports it. +AX_CXX_COMPILE_STDCXX(17, noext, mandatory) # Check for libinjection if ! test -f "${srcdir}/others/libinjection/src/libinjection_html5.c"; then diff --git a/examples/reading_logs_via_rule_message/Makefile.am b/examples/reading_logs_via_rule_message/Makefile.am index cab135bc..210edef3 100644 --- a/examples/reading_logs_via_rule_message/Makefile.am +++ b/examples/reading_logs_via_rule_message/Makefile.am @@ -32,7 +32,6 @@ simple_request_LDFLAGS = \ simple_request_CPPFLAGS = \ $(GLOBAL_CFLAGS) \ - -std=c++17 \ -I$(top_builddir)/headers \ -I$(top_builddir) \ -g \ diff --git a/examples/reading_logs_with_offset/Makefile.am b/examples/reading_logs_with_offset/Makefile.am index 33c8959d..f845c583 100644 --- a/examples/reading_logs_with_offset/Makefile.am +++ b/examples/reading_logs_with_offset/Makefile.am @@ -32,7 +32,6 @@ read_LDFLAGS = \ read_CPPFLAGS = \ $(GLOBAL_CFLAGS) \ - -std=c++17 \ -I$(top_builddir)/headers \ -I$(top_builddir) \ -g \ diff --git a/examples/using_bodies_in_chunks/Makefile.am b/examples/using_bodies_in_chunks/Makefile.am index 72f7bd22..aa28fe07 100644 --- a/examples/using_bodies_in_chunks/Makefile.am +++ b/examples/using_bodies_in_chunks/Makefile.am @@ -33,7 +33,6 @@ simple_request_LDFLAGS = \ simple_request_CPPFLAGS = \ $(GLOBAL_CFLAGS) \ - -std=c++17 \ -I$(top_builddir)/headers \ -I$(top_builddir) \ -g \ diff --git a/src/Makefile.am b/src/Makefile.am index fc67cb6c..cf5549e7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -311,7 +311,6 @@ libmodsecurity_la_CFLAGS = libmodsecurity_la_CPPFLAGS = \ - -std=c++17 \ -I.. \ -g \ -I../others \ diff --git a/src/parser/Makefile.am b/src/parser/Makefile.am index 1fc57310..cded6261 100644 --- a/src/parser/Makefile.am +++ b/src/parser/Makefile.am @@ -11,7 +11,6 @@ libmodsec_parser_la_SOURCES = \ test.cc libmodsec_parser_la_CPPFLAGS = \ - -std=c++17 \ -I../.. \ -I../../headers \ -I../../others \ diff --git a/test/Makefile.am b/test/Makefile.am index 753e3a38..4d4396ae 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -70,7 +70,6 @@ unit_tests_LDFLAGS = \ unit_tests_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -g \ @@ -126,7 +125,6 @@ regression_tests_LDFLAGS = \ regression_tests_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -g \ @@ -179,7 +177,6 @@ rules_optimization_LDFLAGS = \ $(YAJL_LDFLAGS) rules_optimization_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -g \ diff --git a/test/benchmark/Makefile.am b/test/benchmark/Makefile.am index 865818ca..88da53e8 100644 --- a/test/benchmark/Makefile.am +++ b/test/benchmark/Makefile.am @@ -32,7 +32,6 @@ benchmark_LDFLAGS = \ $(LUA_LDFLAGS) benchmark_CPPFLAGS = \ - -std=c++17 \ -I$(top_builddir)/headers \ $(GLOBAL_CPPFLAGS) \ $(PCRE_CFLAGS) \ diff --git a/test/fuzzer/Makefile.am b/test/fuzzer/Makefile.am index dc1b1e50..ea210240 100644 --- a/test/fuzzer/Makefile.am +++ b/test/fuzzer/Makefile.am @@ -30,7 +30,6 @@ afl_fuzzer_LDADD = \ afl_fuzzer_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -I../../ \ diff --git a/tools/rules-check/Makefile.am b/tools/rules-check/Makefile.am index bd929383..6f398fb2 100644 --- a/tools/rules-check/Makefile.am +++ b/tools/rules-check/Makefile.am @@ -28,7 +28,6 @@ modsec_rules_check_LDFLAGS = \ $(YAJL_LDFLAGS) modsec_rules_check_CPPFLAGS = \ - -std=c++17 \ -I$(top_builddir)/headers \ $(GLOBAL_CPPFLAGS) \ $(PCRE_CFLAGS) \ From 30a68de92d5e619613d5250e16abe199a4c8e4d1 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Tue, 21 May 2024 21:02:25 +0000 Subject: [PATCH 26/75] Creating a std::string with a null pointer is undefined behaviour. - cppreference mentions this about the constructor that receives a const char *: - Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. The behavior is undefined if [s, s + Traits::length(s)) is not a valid range (for example, if s is a null pointer). - C++23 introduces a deleted constructor to prevent this in static scenarios, which is how this issue was detected. --- headers/modsecurity/rules_set_properties.h | 2 +- src/actions/transformations/url_encode.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/headers/modsecurity/rules_set_properties.h b/headers/modsecurity/rules_set_properties.h index 77b11269..643abce8 100644 --- a/headers/modsecurity/rules_set_properties.h +++ b/headers/modsecurity/rules_set_properties.h @@ -333,9 +333,9 @@ class RulesSetProperties { case FalseConfigBoolean: return "False"; case PropertyNotSetConfigBoolean: + default: return "Not set"; } - return NULL; } diff --git a/src/actions/transformations/url_encode.cc b/src/actions/transformations/url_encode.cc index 19ecb334..056755ca 100644 --- a/src/actions/transformations/url_encode.cc +++ b/src/actions/transformations/url_encode.cc @@ -48,7 +48,7 @@ std::string UrlEncode::url_enc(const char *input, len = input_len * 3 + 1; d = rval = reinterpret_cast(malloc(len)); if (rval == NULL) { - return NULL; + return {}; } /* ENH Only encode the characters that really need to be encoded. */ From 18378c10f820356a5ec8adf410e696c2be8a31e2 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Sat, 18 May 2024 20:32:21 +0000 Subject: [PATCH 27/75] Removed unnecessary dynamic_casts --- src/rule_with_actions.cc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index 7314b5c8..e0804946 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -213,7 +213,7 @@ void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction * if (m_ruleId != b.first) { continue; } - actions::Action *a = dynamic_cast(b.second.get()); + actions::Action *a = b.second.get(); if (a->isDisruptive() == true && *a->m_name.get() == "block") { ms_dbg_a(trans, 9, "Rule contains a `block' action"); *containsBlock = true; @@ -266,7 +266,7 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, if (m_ruleId != b.first) { continue; } - actions::Action *a = dynamic_cast(b.second.get()); + actions::Action *a = b.second.get(); executeAction(trans, containsBlock, ruleMessage, a, false); disruptiveAlreadyExecuted = true; } @@ -394,8 +394,7 @@ void RuleWithActions::executeTransformations( for (Transformation *a : m_transformations) { if (none == 0) { - Transformation *t = dynamic_cast(a); - executeTransformation(t, &value, trans, &ret, &path, + executeTransformation(a, &value, trans, &ret, &path, &transformations); } if (a->m_isNone) { @@ -423,8 +422,7 @@ void RuleWithActions::executeTransformations( } Transformation *a = dynamic_cast(b.second.get()); if (none == 0) { - Transformation *t = dynamic_cast(a); - executeTransformation(t, &value, trans, &ret, &path, + executeTransformation(a, &value, trans, &ret, &path, &transformations); } if (a->m_isNone) { @@ -479,7 +477,7 @@ std::vector RuleWithActions::getActionsByName(const std::stri if (m_ruleId != b.first) { continue; } - actions::Action *z = dynamic_cast(b.second.get()); + actions::Action *z = b.second.get(); if (*z->m_name.get() == name) { ret.push_back(z); } @@ -489,7 +487,7 @@ std::vector RuleWithActions::getActionsByName(const std::stri if (m_ruleId != b.first) { continue; } - actions::Action *z = dynamic_cast(b.second.get()); + actions::Action *z = b.second.get(); if (*z->m_name.get() == name) { ret.push_back(z); } From c917d6a2dcc16c910815924b6c3ae5681a28bcfb Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Thu, 8 Aug 2024 12:49:48 -0700 Subject: [PATCH 28/75] Initialize variable in if statement to avoid doing dynamic_cast twice - Refactored duplicate code in RuleWithOperator::getVariablesExceptions - Leveraged auto to simplify declaration of dynamic_cast pointers. --- headers/modsecurity/rule_with_operator.h | 2 +- src/actions/set_var.cc | 18 +- src/parser/seclang-parser.cc | 1567 +++++++++++----------- src/parser/seclang-parser.yy | 15 +- src/rule_with_actions.cc | 21 +- src/rule_with_operator.cc | 53 +- test/optimization/optimization.cc | 6 +- 7 files changed, 839 insertions(+), 843 deletions(-) diff --git a/headers/modsecurity/rule_with_operator.h b/headers/modsecurity/rule_with_operator.h index e2fea4e6..42fa0f9e 100644 --- a/headers/modsecurity/rule_with_operator.h +++ b/headers/modsecurity/rule_with_operator.h @@ -50,7 +50,7 @@ class RuleWithOperator : public RuleWithActions { bool evaluate(Transaction *transaction, std::shared_ptr rm) override; - void getVariablesExceptions(Transaction *t, + void getVariablesExceptions(Transaction &t, variables::Variables *exclusion, variables::Variables *addition); inline void getFinalVars(variables::Variables *vars, variables::Variables *eclusion, Transaction *trans); diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc index 6befdf0c..f30ae188 100644 --- a/src/actions/set_var.cc +++ b/src/actions/set_var.cc @@ -51,18 +51,12 @@ bool SetVar::evaluate(RuleWithActions *rule, Transaction *t) { std::string m_variableNameExpanded; auto *v = m_variable.get(); - variables::Tx_DynamicElement *tx = dynamic_cast< - variables::Tx_DynamicElement *> (v); - variables::Session_DynamicElement *session = dynamic_cast< - variables::Session_DynamicElement *> (v); - variables::Ip_DynamicElement *ip = dynamic_cast< - variables::Ip_DynamicElement *> (v); - variables::Resource_DynamicElement *resource = dynamic_cast< - variables::Resource_DynamicElement *> (v); - variables::Global_DynamicElement *global = dynamic_cast< - variables::Global_DynamicElement *> (v); - variables::User_DynamicElement *user = dynamic_cast< - variables::User_DynamicElement *> (v); + auto tx = dynamic_cast (v); + auto session = dynamic_cast (v); + auto ip = dynamic_cast (v); + auto resource = dynamic_cast (v); + auto global = dynamic_cast (v); + auto user = dynamic_cast (v); if (tx) { m_variableNameExpanded = tx->m_string->evaluate(t, rule); } else if (session) { diff --git a/src/parser/seclang-parser.cc b/src/parser/seclang-parser.cc index 9e18db4d..767b8b22 100644 --- a/src/parser/seclang-parser.cc +++ b/src/parser/seclang-parser.cc @@ -2295,8 +2295,9 @@ namespace yy { std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -2320,11 +2321,11 @@ namespace yy { YYERROR; } } -#line 2324 "seclang-parser.cc" +#line 2325 "seclang-parser.cc" break; case 76: // expression: "DIRECTIVE" variables op -#line 1115 "seclang-parser.yy" +#line 1116 "seclang-parser.yy" { variables::Variables *v = new variables::Variables(); for (auto &i : *yystack_[1].value.as < std::unique_ptr > > > ().get()) { @@ -2343,17 +2344,18 @@ namespace yy { YYERROR; } } -#line 2347 "seclang-parser.cc" +#line 2348 "seclang-parser.cc" break; case 77: // expression: "CONFIG_DIR_SEC_ACTION" actions -#line 1134 "seclang-parser.yy" +#line 1135 "seclang-parser.yy" { std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -2366,18 +2368,19 @@ namespace yy { )); driver.addSecAction(std::move(rule)); } -#line 2370 "seclang-parser.cc" +#line 2372 "seclang-parser.cc" break; case 78: // expression: "DIRECTIVE_SECRULESCRIPT" actions -#line 1153 "seclang-parser.yy" +#line 1155 "seclang-parser.yy" { std::string err; std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -2398,11 +2401,11 @@ namespace yy { YYERROR; } } -#line 2402 "seclang-parser.cc" +#line 2405 "seclang-parser.cc" break; case 79: // expression: "CONFIG_DIR_SEC_DEFAULT_ACTION" actions -#line 1181 "seclang-parser.yy" +#line 1184 "seclang-parser.yy" { bool hasDisruptive = false; std::vector *actions = new std::vector(); @@ -2459,78 +2462,78 @@ namespace yy { delete actions; } -#line 2463 "seclang-parser.cc" +#line 2466 "seclang-parser.cc" break; case 80: // expression: "CONFIG_DIR_SEC_MARKER" -#line 1238 "seclang-parser.yy" +#line 1241 "seclang-parser.yy" { driver.addSecMarker(modsecurity::utils::string::removeBracketsIfNeeded(yystack_[0].value.as < std::string > ()), /* file name */ std::unique_ptr(new std::string(*yystack_[0].location.end.filename)), /* line number */ yystack_[0].location.end.line ); } -#line 2474 "seclang-parser.cc" +#line 2477 "seclang-parser.cc" break; case 81: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_OFF" -#line 1245 "seclang-parser.yy" +#line 1248 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::DisabledRuleEngine; } -#line 2482 "seclang-parser.cc" +#line 2485 "seclang-parser.cc" break; case 82: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_ON" -#line 1249 "seclang-parser.yy" +#line 1252 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::EnabledRuleEngine; } -#line 2490 "seclang-parser.cc" +#line 2493 "seclang-parser.cc" break; case 83: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_DETC" -#line 1253 "seclang-parser.yy" +#line 1256 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::DetectionOnlyRuleEngine; } -#line 2498 "seclang-parser.cc" +#line 2501 "seclang-parser.cc" break; case 84: // expression: "CONFIG_DIR_REQ_BODY" "CONFIG_VALUE_ON" -#line 1257 "seclang-parser.yy" +#line 1260 "seclang-parser.yy" { driver.m_secRequestBodyAccess = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 2506 "seclang-parser.cc" +#line 2509 "seclang-parser.cc" break; case 85: // expression: "CONFIG_DIR_REQ_BODY" "CONFIG_VALUE_OFF" -#line 1261 "seclang-parser.yy" +#line 1264 "seclang-parser.yy" { driver.m_secRequestBodyAccess = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 2514 "seclang-parser.cc" +#line 2517 "seclang-parser.cc" break; case 86: // expression: "CONFIG_DIR_RES_BODY" "CONFIG_VALUE_ON" -#line 1265 "seclang-parser.yy" +#line 1268 "seclang-parser.yy" { driver.m_secResponseBodyAccess = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 2522 "seclang-parser.cc" +#line 2525 "seclang-parser.cc" break; case 87: // expression: "CONFIG_DIR_RES_BODY" "CONFIG_VALUE_OFF" -#line 1269 "seclang-parser.yy" +#line 1272 "seclang-parser.yy" { driver.m_secResponseBodyAccess = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 2530 "seclang-parser.cc" +#line 2533 "seclang-parser.cc" break; case 88: // expression: "CONFIG_SEC_ARGUMENT_SEPARATOR" -#line 1273 "seclang-parser.yy" +#line 1276 "seclang-parser.yy" { if (yystack_[0].value.as < std::string > ().length() != 1) { driver.error(yystack_[1].location, "Argument separator should be set to a single character."); @@ -2539,259 +2542,259 @@ namespace yy { driver.m_secArgumentSeparator.m_value = yystack_[0].value.as < std::string > (); driver.m_secArgumentSeparator.m_set = true; } -#line 2543 "seclang-parser.cc" +#line 2546 "seclang-parser.cc" break; case 89: // expression: "CONFIG_COMPONENT_SIG" -#line 1282 "seclang-parser.yy" +#line 1285 "seclang-parser.yy" { driver.m_components.push_back(yystack_[0].value.as < std::string > ()); } -#line 2551 "seclang-parser.cc" +#line 2554 "seclang-parser.cc" break; case 90: // expression: "CONFIG_CONN_ENGINE" "CONFIG_VALUE_ON" -#line 1286 "seclang-parser.yy" +#line 1289 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecConnEngine is not yet supported."); YYERROR; } -#line 2560 "seclang-parser.cc" +#line 2563 "seclang-parser.cc" break; case 91: // expression: "CONFIG_CONN_ENGINE" "CONFIG_VALUE_OFF" -#line 1291 "seclang-parser.yy" +#line 1294 "seclang-parser.yy" { } -#line 2567 "seclang-parser.cc" +#line 2570 "seclang-parser.cc" break; case 92: // expression: "CONFIG_SEC_WEB_APP_ID" -#line 1294 "seclang-parser.yy" +#line 1297 "seclang-parser.yy" { driver.m_secWebAppId.m_value = yystack_[0].value.as < std::string > (); driver.m_secWebAppId.m_set = true; } -#line 2576 "seclang-parser.cc" +#line 2579 "seclang-parser.cc" break; case 93: // expression: "CONFIG_SEC_SERVER_SIG" -#line 1299 "seclang-parser.yy" +#line 1302 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecServerSignature is not supported."); YYERROR; } -#line 2585 "seclang-parser.cc" +#line 2588 "seclang-parser.cc" break; case 94: // expression: "CONFIG_SEC_CACHE_TRANSFORMATIONS" -#line 1304 "seclang-parser.yy" +#line 1307 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecCacheTransformations is not supported."); YYERROR; } -#line 2594 "seclang-parser.cc" +#line 2597 "seclang-parser.cc" break; case 95: // expression: "CONFIG_SEC_DISABLE_BACKEND_COMPRESS" "CONFIG_VALUE_ON" -#line 1309 "seclang-parser.yy" +#line 1312 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecDisableBackendCompression is not supported."); YYERROR; } -#line 2603 "seclang-parser.cc" +#line 2606 "seclang-parser.cc" break; case 96: // expression: "CONFIG_SEC_DISABLE_BACKEND_COMPRESS" "CONFIG_VALUE_OFF" -#line 1314 "seclang-parser.yy" +#line 1317 "seclang-parser.yy" { } -#line 2610 "seclang-parser.cc" +#line 2613 "seclang-parser.cc" break; case 97: // expression: "CONFIG_CONTENT_INJECTION" "CONFIG_VALUE_ON" -#line 1317 "seclang-parser.yy" +#line 1320 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecContentInjection is not yet supported."); YYERROR; } -#line 2619 "seclang-parser.cc" +#line 2622 "seclang-parser.cc" break; case 98: // expression: "CONFIG_CONTENT_INJECTION" "CONFIG_VALUE_OFF" -#line 1322 "seclang-parser.yy" +#line 1325 "seclang-parser.yy" { } -#line 2626 "seclang-parser.cc" +#line 2629 "seclang-parser.cc" break; case 99: // expression: "CONFIG_SEC_CHROOT_DIR" -#line 1325 "seclang-parser.yy" +#line 1328 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecChrootDir is not supported."); YYERROR; } -#line 2635 "seclang-parser.cc" +#line 2638 "seclang-parser.cc" break; case 100: // expression: "CONFIG_SEC_HASH_ENGINE" "CONFIG_VALUE_ON" -#line 1330 "seclang-parser.yy" +#line 1333 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecHashEngine is not yet supported."); YYERROR; } -#line 2644 "seclang-parser.cc" +#line 2647 "seclang-parser.cc" break; case 101: // expression: "CONFIG_SEC_HASH_ENGINE" "CONFIG_VALUE_OFF" -#line 1335 "seclang-parser.yy" +#line 1338 "seclang-parser.yy" { } -#line 2651 "seclang-parser.cc" +#line 2654 "seclang-parser.cc" break; case 102: // expression: "CONFIG_SEC_HASH_KEY" -#line 1338 "seclang-parser.yy" +#line 1341 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashKey is not yet supported."); YYERROR; } -#line 2660 "seclang-parser.cc" +#line 2663 "seclang-parser.cc" break; case 103: // expression: "CONFIG_SEC_HASH_PARAM" -#line 1343 "seclang-parser.yy" +#line 1346 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashParam is not yet supported."); YYERROR; } -#line 2669 "seclang-parser.cc" +#line 2672 "seclang-parser.cc" break; case 104: // expression: "CONFIG_SEC_HASH_METHOD_RX" -#line 1348 "seclang-parser.yy" +#line 1351 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashMethodRx is not yet supported."); YYERROR; } -#line 2678 "seclang-parser.cc" +#line 2681 "seclang-parser.cc" break; case 105: // expression: "CONFIG_SEC_HASH_METHOD_PM" -#line 1353 "seclang-parser.yy" +#line 1356 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashMethodPm is not yet supported."); YYERROR; } -#line 2687 "seclang-parser.cc" +#line 2690 "seclang-parser.cc" break; case 106: // expression: "CONFIG_DIR_GSB_DB" -#line 1358 "seclang-parser.yy" +#line 1361 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecGsbLookupDb is not supported."); YYERROR; } -#line 2696 "seclang-parser.cc" +#line 2699 "seclang-parser.cc" break; case 107: // expression: "CONFIG_SEC_GUARDIAN_LOG" -#line 1363 "seclang-parser.yy" +#line 1366 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecGuardianLog is not supported."); YYERROR; } -#line 2705 "seclang-parser.cc" +#line 2708 "seclang-parser.cc" break; case 108: // expression: "CONFIG_SEC_INTERCEPT_ON_ERROR" "CONFIG_VALUE_ON" -#line 1368 "seclang-parser.yy" +#line 1371 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecInterceptOnError is not yet supported."); YYERROR; } -#line 2714 "seclang-parser.cc" +#line 2717 "seclang-parser.cc" break; case 109: // expression: "CONFIG_SEC_INTERCEPT_ON_ERROR" "CONFIG_VALUE_OFF" -#line 1373 "seclang-parser.yy" +#line 1376 "seclang-parser.yy" { } -#line 2721 "seclang-parser.cc" +#line 2724 "seclang-parser.cc" break; case 110: // expression: "CONFIG_SEC_CONN_R_STATE_LIMIT" -#line 1376 "seclang-parser.yy" +#line 1379 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecConnReadStateLimit is not yet supported."); YYERROR; } -#line 2730 "seclang-parser.cc" +#line 2733 "seclang-parser.cc" break; case 111: // expression: "CONFIG_SEC_CONN_W_STATE_LIMIT" -#line 1381 "seclang-parser.yy" +#line 1384 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecConnWriteStateLimit is not yet supported."); YYERROR; } -#line 2739 "seclang-parser.cc" +#line 2742 "seclang-parser.cc" break; case 112: // expression: "CONFIG_SEC_SENSOR_ID" -#line 1386 "seclang-parser.yy" +#line 1389 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecSensorId is not yet supported."); YYERROR; } -#line 2748 "seclang-parser.cc" +#line 2751 "seclang-parser.cc" break; case 113: // expression: "CONFIG_SEC_RULE_INHERITANCE" "CONFIG_VALUE_ON" -#line 1391 "seclang-parser.yy" +#line 1394 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecRuleInheritance is not yet supported."); YYERROR; } -#line 2757 "seclang-parser.cc" +#line 2760 "seclang-parser.cc" break; case 114: // expression: "CONFIG_SEC_RULE_INHERITANCE" "CONFIG_VALUE_OFF" -#line 1396 "seclang-parser.yy" +#line 1399 "seclang-parser.yy" { } -#line 2764 "seclang-parser.cc" +#line 2767 "seclang-parser.cc" break; case 115: // expression: "CONFIG_SEC_RULE_PERF_TIME" -#line 1399 "seclang-parser.yy" +#line 1402 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecRulePerfTime is not yet supported."); YYERROR; } -#line 2773 "seclang-parser.cc" +#line 2776 "seclang-parser.cc" break; case 116: // expression: "CONFIG_SEC_STREAM_IN_BODY_INSPECTION" -#line 1404 "seclang-parser.yy" +#line 1407 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecStreamInBodyInspection is not supported."); YYERROR; } -#line 2782 "seclang-parser.cc" +#line 2785 "seclang-parser.cc" break; case 117: // expression: "CONFIG_SEC_STREAM_OUT_BODY_INSPECTION" -#line 1409 "seclang-parser.yy" +#line 1412 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecStreamOutBodyInspection is not supported."); YYERROR; } -#line 2791 "seclang-parser.cc" +#line 2794 "seclang-parser.cc" break; case 118: // expression: "CONFIG_SEC_RULE_REMOVE_BY_ID" -#line 1414 "seclang-parser.yy" +#line 1417 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.load(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2804,11 +2807,11 @@ namespace yy { YYERROR; } } -#line 2808 "seclang-parser.cc" +#line 2811 "seclang-parser.cc" break; case 119: // expression: "CONFIG_SEC_RULE_REMOVE_BY_TAG" -#line 1427 "seclang-parser.yy" +#line 1430 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadRemoveRuleByTag(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2821,11 +2824,11 @@ namespace yy { YYERROR; } } -#line 2825 "seclang-parser.cc" +#line 2828 "seclang-parser.cc" break; case 120: // expression: "CONFIG_SEC_RULE_REMOVE_BY_MSG" -#line 1440 "seclang-parser.yy" +#line 1443 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadRemoveRuleByMsg(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2838,11 +2841,11 @@ namespace yy { YYERROR; } } -#line 2842 "seclang-parser.cc" +#line 2845 "seclang-parser.cc" break; case 121: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG" variables_pre_process -#line 1453 "seclang-parser.yy" +#line 1456 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadUpdateTargetByTag(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > > > ()), &error) == false) { @@ -2855,11 +2858,11 @@ namespace yy { YYERROR; } } -#line 2859 "seclang-parser.cc" +#line 2862 "seclang-parser.cc" break; case 122: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG" variables_pre_process -#line 1466 "seclang-parser.yy" +#line 1469 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadUpdateTargetByMsg(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > > > ()), &error) == false) { @@ -2872,11 +2875,11 @@ namespace yy { YYERROR; } } -#line 2876 "seclang-parser.cc" +#line 2879 "seclang-parser.cc" break; case 123: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID" variables_pre_process -#line 1479 "seclang-parser.yy" +#line 1482 "seclang-parser.yy" { std::string error; double ruleId; @@ -2902,11 +2905,11 @@ namespace yy { YYERROR; } } -#line 2906 "seclang-parser.cc" +#line 2909 "seclang-parser.cc" break; case 124: // expression: "CONFIG_SEC_RULE_UPDATE_ACTION_BY_ID" actions -#line 1505 "seclang-parser.yy" +#line 1508 "seclang-parser.yy" { std::string error; double ruleId; @@ -2933,11 +2936,11 @@ namespace yy { YYERROR; } } -#line 2937 "seclang-parser.cc" +#line 2940 "seclang-parser.cc" break; case 125: // expression: "CONFIG_DIR_DEBUG_LVL" -#line 1533 "seclang-parser.yy" +#line 1536 "seclang-parser.yy" { if (driver.m_debugLog != NULL) { driver.m_debugLog->setDebugLogLevel(atoi(yystack_[0].value.as < std::string > ().c_str())); @@ -2949,11 +2952,11 @@ namespace yy { YYERROR; } } -#line 2953 "seclang-parser.cc" +#line 2956 "seclang-parser.cc" break; case 126: // expression: "CONFIG_DIR_DEBUG_LOG" -#line 1545 "seclang-parser.yy" +#line 1548 "seclang-parser.yy" { if (driver.m_debugLog != NULL) { std::string error; @@ -2972,11 +2975,11 @@ namespace yy { YYERROR; } } -#line 2976 "seclang-parser.cc" +#line 2979 "seclang-parser.cc" break; case 127: // expression: "CONFIG_DIR_GEO_DB" -#line 1565 "seclang-parser.yy" +#line 1568 "seclang-parser.yy" { #if defined(WITH_GEOIP) or defined(WITH_MAXMIND) std::string err; @@ -3003,47 +3006,47 @@ namespace yy { YYERROR; #endif // WITH_GEOIP } -#line 3007 "seclang-parser.cc" +#line 3010 "seclang-parser.cc" break; case 128: // expression: "CONFIG_DIR_ARGS_LIMIT" -#line 1592 "seclang-parser.yy" +#line 1595 "seclang-parser.yy" { driver.m_argumentsLimit.m_set = true; driver.m_argumentsLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3016 "seclang-parser.cc" +#line 3019 "seclang-parser.cc" break; case 129: // expression: "CONFIG_DIR_REQ_BODY_JSON_DEPTH_LIMIT" -#line 1597 "seclang-parser.yy" +#line 1600 "seclang-parser.yy" { driver.m_requestBodyJsonDepthLimit.m_set = true; driver.m_requestBodyJsonDepthLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3025 "seclang-parser.cc" +#line 3028 "seclang-parser.cc" break; case 130: // expression: "CONFIG_DIR_REQ_BODY_LIMIT" -#line 1603 "seclang-parser.yy" +#line 1606 "seclang-parser.yy" { driver.m_requestBodyLimit.m_set = true; driver.m_requestBodyLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3034 "seclang-parser.cc" +#line 3037 "seclang-parser.cc" break; case 131: // expression: "CONFIG_DIR_REQ_BODY_NO_FILES_LIMIT" -#line 1608 "seclang-parser.yy" +#line 1611 "seclang-parser.yy" { driver.m_requestBodyNoFilesLimit.m_set = true; driver.m_requestBodyNoFilesLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3043 "seclang-parser.cc" +#line 3046 "seclang-parser.cc" break; case 132: // expression: "CONFIG_DIR_REQ_BODY_IN_MEMORY_LIMIT" -#line 1613 "seclang-parser.yy" +#line 1616 "seclang-parser.yy" { std::stringstream ss; ss << "As of ModSecurity version 3.0, SecRequestBodyInMemoryLimit is no longer "; @@ -3052,77 +3055,77 @@ namespace yy { driver.error(yystack_[1].location, ss.str()); YYERROR; } -#line 3056 "seclang-parser.cc" +#line 3059 "seclang-parser.cc" break; case 133: // expression: "CONFIG_DIR_RES_BODY_LIMIT" -#line 1622 "seclang-parser.yy" +#line 1625 "seclang-parser.yy" { driver.m_responseBodyLimit.m_set = true; driver.m_responseBodyLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3065 "seclang-parser.cc" +#line 3068 "seclang-parser.cc" break; case 134: // expression: "CONFIG_DIR_REQ_BODY_LIMIT_ACTION" "CONFIG_VALUE_PROCESS_PARTIAL" -#line 1627 "seclang-parser.yy" +#line 1630 "seclang-parser.yy" { driver.m_requestBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::ProcessPartialBodyLimitAction; } -#line 3073 "seclang-parser.cc" +#line 3076 "seclang-parser.cc" break; case 135: // expression: "CONFIG_DIR_REQ_BODY_LIMIT_ACTION" "CONFIG_VALUE_REJECT" -#line 1631 "seclang-parser.yy" +#line 1634 "seclang-parser.yy" { driver.m_requestBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::RejectBodyLimitAction; } -#line 3081 "seclang-parser.cc" +#line 3084 "seclang-parser.cc" break; case 136: // expression: "CONFIG_DIR_RES_BODY_LIMIT_ACTION" "CONFIG_VALUE_PROCESS_PARTIAL" -#line 1635 "seclang-parser.yy" +#line 1638 "seclang-parser.yy" { driver.m_responseBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::ProcessPartialBodyLimitAction; } -#line 3089 "seclang-parser.cc" +#line 3092 "seclang-parser.cc" break; case 137: // expression: "CONFIG_DIR_RES_BODY_LIMIT_ACTION" "CONFIG_VALUE_REJECT" -#line 1639 "seclang-parser.yy" +#line 1642 "seclang-parser.yy" { driver.m_responseBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::RejectBodyLimitAction; } -#line 3097 "seclang-parser.cc" +#line 3100 "seclang-parser.cc" break; case 138: // expression: "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION" "CONFIG_VALUE_ABORT" -#line 1643 "seclang-parser.yy" +#line 1646 "seclang-parser.yy" { driver.m_remoteRulesActionOnFailed = RulesSet::OnFailedRemoteRulesAction::AbortOnFailedRemoteRulesAction; } -#line 3105 "seclang-parser.cc" +#line 3108 "seclang-parser.cc" break; case 139: // expression: "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION" "CONFIG_VALUE_WARN" -#line 1647 "seclang-parser.yy" +#line 1650 "seclang-parser.yy" { driver.m_remoteRulesActionOnFailed = RulesSet::OnFailedRemoteRulesAction::WarnOnFailedRemoteRulesAction; } -#line 3113 "seclang-parser.cc" +#line 3116 "seclang-parser.cc" break; case 141: // expression: "CONFIG_DIR_PCRE_MATCH_LIMIT" -#line 1656 "seclang-parser.yy" +#line 1659 "seclang-parser.yy" { driver.m_pcreMatchLimit.m_set = true; driver.m_pcreMatchLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3122 "seclang-parser.cc" +#line 3125 "seclang-parser.cc" break; case 142: // expression: "CONGIG_DIR_RESPONSE_BODY_MP" -#line 1661 "seclang-parser.yy" +#line 1664 "seclang-parser.yy" { std::istringstream buf(yystack_[0].value.as < std::string > ()); std::istream_iterator beg(buf), end; @@ -3134,37 +3137,37 @@ namespace yy { driver.m_responseBodyTypeToBeInspected.m_value.insert(*it); } } -#line 3138 "seclang-parser.cc" +#line 3141 "seclang-parser.cc" break; case 143: // expression: "CONGIG_DIR_RESPONSE_BODY_MP_CLEAR" -#line 1673 "seclang-parser.yy" +#line 1676 "seclang-parser.yy" { driver.m_responseBodyTypeToBeInspected.m_set = true; driver.m_responseBodyTypeToBeInspected.m_clear = true; driver.m_responseBodyTypeToBeInspected.m_value.clear(); } -#line 3148 "seclang-parser.cc" +#line 3151 "seclang-parser.cc" break; case 144: // expression: "CONFIG_XML_EXTERNAL_ENTITY" "CONFIG_VALUE_OFF" -#line 1679 "seclang-parser.yy" +#line 1682 "seclang-parser.yy" { driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 3156 "seclang-parser.cc" +#line 3159 "seclang-parser.cc" break; case 145: // expression: "CONFIG_XML_EXTERNAL_ENTITY" "CONFIG_VALUE_ON" -#line 1683 "seclang-parser.yy" +#line 1686 "seclang-parser.yy" { driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 3164 "seclang-parser.cc" +#line 3167 "seclang-parser.cc" break; case 146: // expression: "CONGIG_DIR_SEC_TMP_DIR" -#line 1687 "seclang-parser.yy" +#line 1690 "seclang-parser.yy" { /* Parser error disabled to avoid breaking default installations with modsecurity.conf-recommended std::stringstream ss; @@ -3175,31 +3178,31 @@ namespace yy { YYERROR; */ } -#line 3179 "seclang-parser.cc" +#line 3182 "seclang-parser.cc" break; case 149: // expression: "CONGIG_DIR_SEC_COOKIE_FORMAT" -#line 1708 "seclang-parser.yy" +#line 1711 "seclang-parser.yy" { if (atoi(yystack_[0].value.as < std::string > ().c_str()) == 1) { driver.error(yystack_[1].location, "SecCookieFormat 1 is not yet supported."); YYERROR; } } -#line 3190 "seclang-parser.cc" +#line 3193 "seclang-parser.cc" break; case 150: // expression: "CONFIG_SEC_COOKIEV0_SEPARATOR" -#line 1715 "seclang-parser.yy" +#line 1718 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecCookieV0Separator is not yet supported."); YYERROR; } -#line 3199 "seclang-parser.cc" +#line 3202 "seclang-parser.cc" break; case 152: // expression: "CONFIG_DIR_UNICODE_MAP_FILE" -#line 1725 "seclang-parser.yy" +#line 1728 "seclang-parser.yy" { std::string error; std::vector param; @@ -3253,31 +3256,31 @@ namespace yy { } } -#line 3257 "seclang-parser.cc" +#line 3260 "seclang-parser.cc" break; case 153: // expression: "CONFIG_SEC_COLLECTION_TIMEOUT" -#line 1779 "seclang-parser.yy" +#line 1782 "seclang-parser.yy" { /* Parser error disabled to avoid breaking default CRS installations with crs-setup.conf-recommended driver.error(@0, "SecCollectionTimeout is not yet supported."); YYERROR; */ } -#line 3268 "seclang-parser.cc" +#line 3271 "seclang-parser.cc" break; case 154: // expression: "CONFIG_SEC_HTTP_BLKEY" -#line 1786 "seclang-parser.yy" +#line 1789 "seclang-parser.yy" { driver.m_httpblKey.m_set = true; driver.m_httpblKey.m_value = yystack_[0].value.as < std::string > (); } -#line 3277 "seclang-parser.cc" +#line 3280 "seclang-parser.cc" break; case 155: // variables: variables_pre_process -#line 1794 "seclang-parser.yy" +#line 1797 "seclang-parser.yy" { std::unique_ptr > > originalList = std::move(yystack_[0].value.as < std::unique_ptr > > > ()); std::unique_ptr>> newList(new std::vector>()); @@ -3311,2401 +3314,2401 @@ namespace yy { } yylhs.value.as < std::unique_ptr > > > () = std::move(newNewList); } -#line 3315 "seclang-parser.cc" +#line 3318 "seclang-parser.cc" break; case 156: // variables_pre_process: variables_may_be_quoted -#line 1831 "seclang-parser.yy" +#line 1834 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[0].value.as < std::unique_ptr > > > ()); } -#line 3323 "seclang-parser.cc" +#line 3326 "seclang-parser.cc" break; case 157: // variables_pre_process: "QUOTATION_MARK" variables_may_be_quoted "QUOTATION_MARK" -#line 1835 "seclang-parser.yy" +#line 1838 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[1].value.as < std::unique_ptr > > > ()); } -#line 3331 "seclang-parser.cc" +#line 3334 "seclang-parser.cc" break; case 158: // variables_may_be_quoted: variables_may_be_quoted PIPE var -#line 1842 "seclang-parser.yy" +#line 1845 "seclang-parser.yy" { yystack_[2].value.as < std::unique_ptr > > > ()->push_back(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[2].value.as < std::unique_ptr > > > ()); } -#line 3340 "seclang-parser.cc" +#line 3343 "seclang-parser.cc" break; case 159: // variables_may_be_quoted: variables_may_be_quoted PIPE VAR_EXCLUSION var -#line 1847 "seclang-parser.yy" +#line 1850 "seclang-parser.yy" { std::unique_ptr c(new VariableModificatorExclusion(std::move(yystack_[0].value.as < std::unique_ptr > ()))); yystack_[3].value.as < std::unique_ptr > > > ()->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[3].value.as < std::unique_ptr > > > ()); } -#line 3350 "seclang-parser.cc" +#line 3353 "seclang-parser.cc" break; case 160: // variables_may_be_quoted: variables_may_be_quoted PIPE VAR_COUNT var -#line 1853 "seclang-parser.yy" +#line 1856 "seclang-parser.yy" { std::unique_ptr c(new VariableModificatorCount(std::move(yystack_[0].value.as < std::unique_ptr > ()))); yystack_[3].value.as < std::unique_ptr > > > ()->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[3].value.as < std::unique_ptr > > > ()); } -#line 3360 "seclang-parser.cc" +#line 3363 "seclang-parser.cc" break; case 161: // variables_may_be_quoted: var -#line 1859 "seclang-parser.yy" +#line 1862 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); b->push_back(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3370 "seclang-parser.cc" +#line 3373 "seclang-parser.cc" break; case 162: // variables_may_be_quoted: VAR_EXCLUSION var -#line 1865 "seclang-parser.yy" +#line 1868 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); std::unique_ptr c(new VariableModificatorExclusion(std::move(yystack_[0].value.as < std::unique_ptr > ()))); b->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3381 "seclang-parser.cc" +#line 3384 "seclang-parser.cc" break; case 163: // variables_may_be_quoted: VAR_COUNT var -#line 1872 "seclang-parser.yy" +#line 1875 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); std::unique_ptr c(new VariableModificatorCount(std::move(yystack_[0].value.as < std::unique_ptr > ()))); b->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3392 "seclang-parser.cc" +#line 3395 "seclang-parser.cc" break; case 164: // var: VARIABLE_ARGS "Dictionary element" -#line 1882 "seclang-parser.yy" +#line 1885 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3400 "seclang-parser.cc" +#line 3403 "seclang-parser.cc" break; case 165: // var: VARIABLE_ARGS "Dictionary element, selected by regexp" -#line 1886 "seclang-parser.yy" +#line 1889 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3408 "seclang-parser.cc" +#line 3411 "seclang-parser.cc" break; case 166: // var: VARIABLE_ARGS -#line 1890 "seclang-parser.yy" +#line 1893 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_NoDictElement()); } -#line 3416 "seclang-parser.cc" +#line 3419 "seclang-parser.cc" break; case 167: // var: VARIABLE_ARGS_POST "Dictionary element" -#line 1894 "seclang-parser.yy" +#line 1897 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3424 "seclang-parser.cc" +#line 3427 "seclang-parser.cc" break; case 168: // var: VARIABLE_ARGS_POST "Dictionary element, selected by regexp" -#line 1898 "seclang-parser.yy" +#line 1901 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3432 "seclang-parser.cc" +#line 3435 "seclang-parser.cc" break; case 169: // var: VARIABLE_ARGS_POST -#line 1902 "seclang-parser.yy" +#line 1905 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_NoDictElement()); } -#line 3440 "seclang-parser.cc" +#line 3443 "seclang-parser.cc" break; case 170: // var: VARIABLE_ARGS_GET "Dictionary element" -#line 1906 "seclang-parser.yy" +#line 1909 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3448 "seclang-parser.cc" +#line 3451 "seclang-parser.cc" break; case 171: // var: VARIABLE_ARGS_GET "Dictionary element, selected by regexp" -#line 1910 "seclang-parser.yy" +#line 1913 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3456 "seclang-parser.cc" +#line 3459 "seclang-parser.cc" break; case 172: // var: VARIABLE_ARGS_GET -#line 1914 "seclang-parser.yy" +#line 1917 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_NoDictElement()); } -#line 3464 "seclang-parser.cc" +#line 3467 "seclang-parser.cc" break; case 173: // var: VARIABLE_FILES_SIZES "Dictionary element" -#line 1918 "seclang-parser.yy" +#line 1921 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3472 "seclang-parser.cc" +#line 3475 "seclang-parser.cc" break; case 174: // var: VARIABLE_FILES_SIZES "Dictionary element, selected by regexp" -#line 1922 "seclang-parser.yy" +#line 1925 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3480 "seclang-parser.cc" +#line 3483 "seclang-parser.cc" break; case 175: // var: VARIABLE_FILES_SIZES -#line 1926 "seclang-parser.yy" +#line 1929 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_NoDictElement()); } -#line 3488 "seclang-parser.cc" +#line 3491 "seclang-parser.cc" break; case 176: // var: VARIABLE_FILES_NAMES "Dictionary element" -#line 1930 "seclang-parser.yy" +#line 1933 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3496 "seclang-parser.cc" +#line 3499 "seclang-parser.cc" break; case 177: // var: VARIABLE_FILES_NAMES "Dictionary element, selected by regexp" -#line 1934 "seclang-parser.yy" +#line 1937 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3504 "seclang-parser.cc" +#line 3507 "seclang-parser.cc" break; case 178: // var: VARIABLE_FILES_NAMES -#line 1938 "seclang-parser.yy" +#line 1941 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_NoDictElement()); } -#line 3512 "seclang-parser.cc" +#line 3515 "seclang-parser.cc" break; case 179: // var: VARIABLE_FILES_TMP_CONTENT "Dictionary element" -#line 1942 "seclang-parser.yy" +#line 1945 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3520 "seclang-parser.cc" +#line 3523 "seclang-parser.cc" break; case 180: // var: VARIABLE_FILES_TMP_CONTENT "Dictionary element, selected by regexp" -#line 1946 "seclang-parser.yy" +#line 1949 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3528 "seclang-parser.cc" +#line 3531 "seclang-parser.cc" break; case 181: // var: VARIABLE_FILES_TMP_CONTENT -#line 1950 "seclang-parser.yy" +#line 1953 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_NoDictElement()); } -#line 3536 "seclang-parser.cc" +#line 3539 "seclang-parser.cc" break; case 182: // var: VARIABLE_MULTIPART_FILENAME "Dictionary element" -#line 1954 "seclang-parser.yy" +#line 1957 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3544 "seclang-parser.cc" +#line 3547 "seclang-parser.cc" break; case 183: // var: VARIABLE_MULTIPART_FILENAME "Dictionary element, selected by regexp" -#line 1958 "seclang-parser.yy" +#line 1961 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3552 "seclang-parser.cc" +#line 3555 "seclang-parser.cc" break; case 184: // var: VARIABLE_MULTIPART_FILENAME -#line 1962 "seclang-parser.yy" +#line 1965 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_NoDictElement()); } -#line 3560 "seclang-parser.cc" +#line 3563 "seclang-parser.cc" break; case 185: // var: VARIABLE_MULTIPART_NAME "Dictionary element" -#line 1966 "seclang-parser.yy" +#line 1969 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3568 "seclang-parser.cc" +#line 3571 "seclang-parser.cc" break; case 186: // var: VARIABLE_MULTIPART_NAME "Dictionary element, selected by regexp" -#line 1970 "seclang-parser.yy" +#line 1973 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3576 "seclang-parser.cc" +#line 3579 "seclang-parser.cc" break; case 187: // var: VARIABLE_MULTIPART_NAME -#line 1974 "seclang-parser.yy" +#line 1977 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_NoDictElement()); } -#line 3584 "seclang-parser.cc" +#line 3587 "seclang-parser.cc" break; case 188: // var: VARIABLE_MATCHED_VARS_NAMES "Dictionary element" -#line 1978 "seclang-parser.yy" +#line 1981 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3592 "seclang-parser.cc" +#line 3595 "seclang-parser.cc" break; case 189: // var: VARIABLE_MATCHED_VARS_NAMES "Dictionary element, selected by regexp" -#line 1982 "seclang-parser.yy" +#line 1985 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3600 "seclang-parser.cc" +#line 3603 "seclang-parser.cc" break; case 190: // var: VARIABLE_MATCHED_VARS_NAMES -#line 1986 "seclang-parser.yy" +#line 1989 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_NoDictElement()); } -#line 3608 "seclang-parser.cc" +#line 3611 "seclang-parser.cc" break; case 191: // var: VARIABLE_MATCHED_VARS "Dictionary element" -#line 1990 "seclang-parser.yy" +#line 1993 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3616 "seclang-parser.cc" +#line 3619 "seclang-parser.cc" break; case 192: // var: VARIABLE_MATCHED_VARS "Dictionary element, selected by regexp" -#line 1994 "seclang-parser.yy" +#line 1997 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3624 "seclang-parser.cc" +#line 3627 "seclang-parser.cc" break; case 193: // var: VARIABLE_MATCHED_VARS -#line 1998 "seclang-parser.yy" +#line 2001 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_NoDictElement()); } -#line 3632 "seclang-parser.cc" +#line 3635 "seclang-parser.cc" break; case 194: // var: VARIABLE_FILES "Dictionary element" -#line 2002 "seclang-parser.yy" +#line 2005 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3640 "seclang-parser.cc" +#line 3643 "seclang-parser.cc" break; case 195: // var: VARIABLE_FILES "Dictionary element, selected by regexp" -#line 2006 "seclang-parser.yy" +#line 2009 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3648 "seclang-parser.cc" +#line 3651 "seclang-parser.cc" break; case 196: // var: VARIABLE_FILES -#line 2010 "seclang-parser.yy" +#line 2013 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_NoDictElement()); } -#line 3656 "seclang-parser.cc" +#line 3659 "seclang-parser.cc" break; case 197: // var: VARIABLE_REQUEST_COOKIES "Dictionary element" -#line 2014 "seclang-parser.yy" +#line 2017 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3664 "seclang-parser.cc" +#line 3667 "seclang-parser.cc" break; case 198: // var: VARIABLE_REQUEST_COOKIES "Dictionary element, selected by regexp" -#line 2018 "seclang-parser.yy" +#line 2021 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3672 "seclang-parser.cc" +#line 3675 "seclang-parser.cc" break; case 199: // var: VARIABLE_REQUEST_COOKIES -#line 2022 "seclang-parser.yy" +#line 2025 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_NoDictElement()); } -#line 3680 "seclang-parser.cc" +#line 3683 "seclang-parser.cc" break; case 200: // var: VARIABLE_REQUEST_HEADERS "Dictionary element" -#line 2026 "seclang-parser.yy" +#line 2029 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3688 "seclang-parser.cc" +#line 3691 "seclang-parser.cc" break; case 201: // var: VARIABLE_REQUEST_HEADERS "Dictionary element, selected by regexp" -#line 2030 "seclang-parser.yy" +#line 2033 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3696 "seclang-parser.cc" +#line 3699 "seclang-parser.cc" break; case 202: // var: VARIABLE_REQUEST_HEADERS -#line 2034 "seclang-parser.yy" +#line 2037 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_NoDictElement()); } -#line 3704 "seclang-parser.cc" +#line 3707 "seclang-parser.cc" break; case 203: // var: VARIABLE_RESPONSE_HEADERS "Dictionary element" -#line 2038 "seclang-parser.yy" +#line 2041 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3712 "seclang-parser.cc" +#line 3715 "seclang-parser.cc" break; case 204: // var: VARIABLE_RESPONSE_HEADERS "Dictionary element, selected by regexp" -#line 2042 "seclang-parser.yy" +#line 2045 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3720 "seclang-parser.cc" +#line 3723 "seclang-parser.cc" break; case 205: // var: VARIABLE_RESPONSE_HEADERS -#line 2046 "seclang-parser.yy" +#line 2049 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_NoDictElement()); } -#line 3728 "seclang-parser.cc" +#line 3731 "seclang-parser.cc" break; case 206: // var: VARIABLE_GEO "Dictionary element" -#line 2050 "seclang-parser.yy" +#line 2053 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3736 "seclang-parser.cc" +#line 3739 "seclang-parser.cc" break; case 207: // var: VARIABLE_GEO "Dictionary element, selected by regexp" -#line 2054 "seclang-parser.yy" +#line 2057 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3744 "seclang-parser.cc" +#line 3747 "seclang-parser.cc" break; case 208: // var: VARIABLE_GEO -#line 2058 "seclang-parser.yy" +#line 2061 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_NoDictElement()); } -#line 3752 "seclang-parser.cc" +#line 3755 "seclang-parser.cc" break; case 209: // var: VARIABLE_REQUEST_COOKIES_NAMES "Dictionary element" -#line 2062 "seclang-parser.yy" +#line 2065 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3760 "seclang-parser.cc" +#line 3763 "seclang-parser.cc" break; case 210: // var: VARIABLE_REQUEST_COOKIES_NAMES "Dictionary element, selected by regexp" -#line 2066 "seclang-parser.yy" +#line 2069 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3768 "seclang-parser.cc" +#line 3771 "seclang-parser.cc" break; case 211: // var: VARIABLE_REQUEST_COOKIES_NAMES -#line 2070 "seclang-parser.yy" +#line 2073 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_NoDictElement()); } -#line 3776 "seclang-parser.cc" +#line 3779 "seclang-parser.cc" break; case 212: // var: VARIABLE_MULTIPART_PART_HEADERS "Dictionary element" -#line 2074 "seclang-parser.yy" +#line 2077 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartPartHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3784 "seclang-parser.cc" +#line 3787 "seclang-parser.cc" break; case 213: // var: VARIABLE_MULTIPART_PART_HEADERS "Dictionary element, selected by regexp" -#line 2078 "seclang-parser.yy" +#line 2081 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartPartHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3792 "seclang-parser.cc" +#line 3795 "seclang-parser.cc" break; case 214: // var: VARIABLE_MULTIPART_PART_HEADERS -#line 2082 "seclang-parser.yy" +#line 2085 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartPartHeaders_NoDictElement()); } -#line 3800 "seclang-parser.cc" +#line 3803 "seclang-parser.cc" break; case 215: // var: VARIABLE_RULE "Dictionary element" -#line 2086 "seclang-parser.yy" +#line 2089 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3808 "seclang-parser.cc" +#line 3811 "seclang-parser.cc" break; case 216: // var: VARIABLE_RULE "Dictionary element, selected by regexp" -#line 2090 "seclang-parser.yy" +#line 2093 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3816 "seclang-parser.cc" +#line 3819 "seclang-parser.cc" break; case 217: // var: VARIABLE_RULE -#line 2094 "seclang-parser.yy" +#line 2097 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_NoDictElement()); } -#line 3824 "seclang-parser.cc" +#line 3827 "seclang-parser.cc" break; case 218: // var: "RUN_TIME_VAR_ENV" "Dictionary element" -#line 2098 "seclang-parser.yy" +#line 2101 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV:" + yystack_[0].value.as < std::string > ())); } -#line 3832 "seclang-parser.cc" +#line 3835 "seclang-parser.cc" break; case 219: // var: "RUN_TIME_VAR_ENV" "Dictionary element, selected by regexp" -#line 2102 "seclang-parser.yy" +#line 2105 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV:" + yystack_[0].value.as < std::string > ())); } -#line 3840 "seclang-parser.cc" +#line 3843 "seclang-parser.cc" break; case 220: // var: "RUN_TIME_VAR_ENV" -#line 2106 "seclang-parser.yy" +#line 2109 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV")); } -#line 3848 "seclang-parser.cc" +#line 3851 "seclang-parser.cc" break; case 221: // var: "RUN_TIME_VAR_XML" "Dictionary element" -#line 2110 "seclang-parser.yy" +#line 2113 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML("XML:" + yystack_[0].value.as < std::string > ())); } -#line 3856 "seclang-parser.cc" +#line 3859 "seclang-parser.cc" break; case 222: // var: "RUN_TIME_VAR_XML" "Dictionary element, selected by regexp" -#line 2114 "seclang-parser.yy" +#line 2117 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML("XML:" + yystack_[0].value.as < std::string > ())); } -#line 3864 "seclang-parser.cc" +#line 3867 "seclang-parser.cc" break; case 223: // var: "RUN_TIME_VAR_XML" -#line 2118 "seclang-parser.yy" +#line 2121 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML_NoDictElement()); } -#line 3872 "seclang-parser.cc" +#line 3875 "seclang-parser.cc" break; case 224: // var: "FILES_TMPNAMES" "Dictionary element" -#line 2122 "seclang-parser.yy" +#line 2125 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3880 "seclang-parser.cc" +#line 3883 "seclang-parser.cc" break; case 225: // var: "FILES_TMPNAMES" "Dictionary element, selected by regexp" -#line 2126 "seclang-parser.yy" +#line 2129 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3888 "seclang-parser.cc" +#line 3891 "seclang-parser.cc" break; case 226: // var: "FILES_TMPNAMES" -#line 2130 "seclang-parser.yy" +#line 2133 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_NoDictElement()); } -#line 3896 "seclang-parser.cc" +#line 3899 "seclang-parser.cc" break; case 227: // var: "RESOURCE" run_time_string -#line 2134 "seclang-parser.yy" +#line 2137 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3904 "seclang-parser.cc" +#line 3907 "seclang-parser.cc" break; case 228: // var: "RESOURCE" "Dictionary element" -#line 2138 "seclang-parser.yy" +#line 2141 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3912 "seclang-parser.cc" +#line 3915 "seclang-parser.cc" break; case 229: // var: "RESOURCE" "Dictionary element, selected by regexp" -#line 2142 "seclang-parser.yy" +#line 2145 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3920 "seclang-parser.cc" +#line 3923 "seclang-parser.cc" break; case 230: // var: "RESOURCE" -#line 2146 "seclang-parser.yy" +#line 2149 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_NoDictElement()); } -#line 3928 "seclang-parser.cc" +#line 3931 "seclang-parser.cc" break; case 231: // var: "VARIABLE_IP" run_time_string -#line 2150 "seclang-parser.yy" +#line 2153 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3936 "seclang-parser.cc" +#line 3939 "seclang-parser.cc" break; case 232: // var: "VARIABLE_IP" "Dictionary element" -#line 2154 "seclang-parser.yy" +#line 2157 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3944 "seclang-parser.cc" +#line 3947 "seclang-parser.cc" break; case 233: // var: "VARIABLE_IP" "Dictionary element, selected by regexp" -#line 2158 "seclang-parser.yy" +#line 2161 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3952 "seclang-parser.cc" +#line 3955 "seclang-parser.cc" break; case 234: // var: "VARIABLE_IP" -#line 2162 "seclang-parser.yy" +#line 2165 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_NoDictElement()); } -#line 3960 "seclang-parser.cc" +#line 3963 "seclang-parser.cc" break; case 235: // var: "VARIABLE_GLOBAL" run_time_string -#line 2166 "seclang-parser.yy" +#line 2169 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3968 "seclang-parser.cc" +#line 3971 "seclang-parser.cc" break; case 236: // var: "VARIABLE_GLOBAL" "Dictionary element" -#line 2170 "seclang-parser.yy" +#line 2173 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3976 "seclang-parser.cc" +#line 3979 "seclang-parser.cc" break; case 237: // var: "VARIABLE_GLOBAL" "Dictionary element, selected by regexp" -#line 2174 "seclang-parser.yy" +#line 2177 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3984 "seclang-parser.cc" +#line 3987 "seclang-parser.cc" break; case 238: // var: "VARIABLE_GLOBAL" -#line 2178 "seclang-parser.yy" +#line 2181 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_NoDictElement()); } -#line 3992 "seclang-parser.cc" +#line 3995 "seclang-parser.cc" break; case 239: // var: "VARIABLE_USER" run_time_string -#line 2182 "seclang-parser.yy" +#line 2185 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 4000 "seclang-parser.cc" +#line 4003 "seclang-parser.cc" break; case 240: // var: "VARIABLE_USER" "Dictionary element" -#line 2186 "seclang-parser.yy" +#line 2189 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4008 "seclang-parser.cc" +#line 4011 "seclang-parser.cc" break; case 241: // var: "VARIABLE_USER" "Dictionary element, selected by regexp" -#line 2190 "seclang-parser.yy" +#line 2193 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4016 "seclang-parser.cc" +#line 4019 "seclang-parser.cc" break; case 242: // var: "VARIABLE_USER" -#line 2194 "seclang-parser.yy" +#line 2197 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_NoDictElement()); } -#line 4024 "seclang-parser.cc" +#line 4027 "seclang-parser.cc" break; case 243: // var: "VARIABLE_TX" run_time_string -#line 2198 "seclang-parser.yy" +#line 2201 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 4032 "seclang-parser.cc" +#line 4035 "seclang-parser.cc" break; case 244: // var: "VARIABLE_TX" "Dictionary element" -#line 2202 "seclang-parser.yy" +#line 2205 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4040 "seclang-parser.cc" +#line 4043 "seclang-parser.cc" break; case 245: // var: "VARIABLE_TX" "Dictionary element, selected by regexp" -#line 2206 "seclang-parser.yy" +#line 2209 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4048 "seclang-parser.cc" +#line 4051 "seclang-parser.cc" break; case 246: // var: "VARIABLE_TX" -#line 2210 "seclang-parser.yy" +#line 2213 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_NoDictElement()); } -#line 4056 "seclang-parser.cc" +#line 4059 "seclang-parser.cc" break; case 247: // var: "VARIABLE_SESSION" run_time_string -#line 2214 "seclang-parser.yy" +#line 2217 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 4064 "seclang-parser.cc" +#line 4067 "seclang-parser.cc" break; case 248: // var: "VARIABLE_SESSION" "Dictionary element" -#line 2218 "seclang-parser.yy" +#line 2221 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4072 "seclang-parser.cc" +#line 4075 "seclang-parser.cc" break; case 249: // var: "VARIABLE_SESSION" "Dictionary element, selected by regexp" -#line 2222 "seclang-parser.yy" +#line 2225 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4080 "seclang-parser.cc" +#line 4083 "seclang-parser.cc" break; case 250: // var: "VARIABLE_SESSION" -#line 2226 "seclang-parser.yy" +#line 2229 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_NoDictElement()); } -#line 4088 "seclang-parser.cc" +#line 4091 "seclang-parser.cc" break; case 251: // var: "Variable ARGS_NAMES" "Dictionary element" -#line 2230 "seclang-parser.yy" +#line 2233 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4096 "seclang-parser.cc" +#line 4099 "seclang-parser.cc" break; case 252: // var: "Variable ARGS_NAMES" "Dictionary element, selected by regexp" -#line 2234 "seclang-parser.yy" +#line 2237 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4104 "seclang-parser.cc" +#line 4107 "seclang-parser.cc" break; case 253: // var: "Variable ARGS_NAMES" -#line 2238 "seclang-parser.yy" +#line 2241 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_NoDictElement()); } -#line 4112 "seclang-parser.cc" +#line 4115 "seclang-parser.cc" break; case 254: // var: VARIABLE_ARGS_GET_NAMES "Dictionary element" -#line 2242 "seclang-parser.yy" +#line 2245 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4120 "seclang-parser.cc" +#line 4123 "seclang-parser.cc" break; case 255: // var: VARIABLE_ARGS_GET_NAMES "Dictionary element, selected by regexp" -#line 2246 "seclang-parser.yy" +#line 2249 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4128 "seclang-parser.cc" +#line 4131 "seclang-parser.cc" break; case 256: // var: VARIABLE_ARGS_GET_NAMES -#line 2250 "seclang-parser.yy" +#line 2253 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_NoDictElement()); } -#line 4136 "seclang-parser.cc" +#line 4139 "seclang-parser.cc" break; case 257: // var: VARIABLE_ARGS_POST_NAMES "Dictionary element" -#line 2255 "seclang-parser.yy" +#line 2258 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4144 "seclang-parser.cc" +#line 4147 "seclang-parser.cc" break; case 258: // var: VARIABLE_ARGS_POST_NAMES "Dictionary element, selected by regexp" -#line 2259 "seclang-parser.yy" +#line 2262 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4152 "seclang-parser.cc" +#line 4155 "seclang-parser.cc" break; case 259: // var: VARIABLE_ARGS_POST_NAMES -#line 2263 "seclang-parser.yy" +#line 2266 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_NoDictElement()); } -#line 4160 "seclang-parser.cc" +#line 4163 "seclang-parser.cc" break; case 260: // var: VARIABLE_REQUEST_HEADERS_NAMES "Dictionary element" -#line 2268 "seclang-parser.yy" +#line 2271 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4168 "seclang-parser.cc" +#line 4171 "seclang-parser.cc" break; case 261: // var: VARIABLE_REQUEST_HEADERS_NAMES "Dictionary element, selected by regexp" -#line 2272 "seclang-parser.yy" +#line 2275 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4176 "seclang-parser.cc" +#line 4179 "seclang-parser.cc" break; case 262: // var: VARIABLE_REQUEST_HEADERS_NAMES -#line 2276 "seclang-parser.yy" +#line 2279 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_NoDictElement()); } -#line 4184 "seclang-parser.cc" +#line 4187 "seclang-parser.cc" break; case 263: // var: VARIABLE_RESPONSE_CONTENT_TYPE -#line 2281 "seclang-parser.yy" +#line 2284 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseContentType()); } -#line 4192 "seclang-parser.cc" +#line 4195 "seclang-parser.cc" break; case 264: // var: VARIABLE_RESPONSE_HEADERS_NAMES "Dictionary element" -#line 2286 "seclang-parser.yy" +#line 2289 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4200 "seclang-parser.cc" +#line 4203 "seclang-parser.cc" break; case 265: // var: VARIABLE_RESPONSE_HEADERS_NAMES "Dictionary element, selected by regexp" -#line 2290 "seclang-parser.yy" +#line 2293 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4208 "seclang-parser.cc" +#line 4211 "seclang-parser.cc" break; case 266: // var: VARIABLE_RESPONSE_HEADERS_NAMES -#line 2294 "seclang-parser.yy" +#line 2297 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_NoDictElement()); } -#line 4216 "seclang-parser.cc" +#line 4219 "seclang-parser.cc" break; case 267: // var: VARIABLE_ARGS_COMBINED_SIZE -#line 2298 "seclang-parser.yy" +#line 2301 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsCombinedSize()); } -#line 4224 "seclang-parser.cc" +#line 4227 "seclang-parser.cc" break; case 268: // var: "AUTH_TYPE" -#line 2302 "seclang-parser.yy" +#line 2305 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::AuthType()); } -#line 4232 "seclang-parser.cc" +#line 4235 "seclang-parser.cc" break; case 269: // var: "FILES_COMBINED_SIZE" -#line 2306 "seclang-parser.yy" +#line 2309 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesCombinedSize()); } -#line 4240 "seclang-parser.cc" +#line 4243 "seclang-parser.cc" break; case 270: // var: "FULL_REQUEST" -#line 2310 "seclang-parser.yy" +#line 2313 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FullRequest()); } -#line 4248 "seclang-parser.cc" +#line 4251 "seclang-parser.cc" break; case 271: // var: "FULL_REQUEST_LENGTH" -#line 2314 "seclang-parser.yy" +#line 2317 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FullRequestLength()); } -#line 4256 "seclang-parser.cc" +#line 4259 "seclang-parser.cc" break; case 272: // var: "INBOUND_DATA_ERROR" -#line 2318 "seclang-parser.yy" +#line 2321 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::InboundDataError()); } -#line 4264 "seclang-parser.cc" +#line 4267 "seclang-parser.cc" break; case 273: // var: "MATCHED_VAR" -#line 2322 "seclang-parser.yy" +#line 2325 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVar()); } -#line 4272 "seclang-parser.cc" +#line 4275 "seclang-parser.cc" break; case 274: // var: "MATCHED_VAR_NAME" -#line 2326 "seclang-parser.yy" +#line 2329 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarName()); } -#line 4280 "seclang-parser.cc" +#line 4283 "seclang-parser.cc" break; case 275: // var: "MSC_PCRE_ERROR" -#line 2330 "seclang-parser.yy" +#line 2333 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MscPcreError()); } -#line 4288 "seclang-parser.cc" +#line 4291 "seclang-parser.cc" break; case 276: // var: "MSC_PCRE_LIMITS_EXCEEDED" -#line 2334 "seclang-parser.yy" +#line 2337 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MscPcreLimitsExceeded()); } -#line 4296 "seclang-parser.cc" +#line 4299 "seclang-parser.cc" break; case 277: // var: VARIABLE_MULTIPART_BOUNDARY_QUOTED -#line 2338 "seclang-parser.yy" +#line 2341 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartBoundaryQuoted()); } -#line 4304 "seclang-parser.cc" +#line 4307 "seclang-parser.cc" break; case 278: // var: VARIABLE_MULTIPART_BOUNDARY_WHITESPACE -#line 2342 "seclang-parser.yy" +#line 2345 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartBoundaryWhiteSpace()); } -#line 4312 "seclang-parser.cc" +#line 4315 "seclang-parser.cc" break; case 279: // var: "MULTIPART_CRLF_LF_LINES" -#line 2346 "seclang-parser.yy" +#line 2349 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartCrlfLFLines()); } -#line 4320 "seclang-parser.cc" +#line 4323 "seclang-parser.cc" break; case 280: // var: "MULTIPART_DATA_AFTER" -#line 2350 "seclang-parser.yy" +#line 2353 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartDateAfter()); } -#line 4328 "seclang-parser.cc" +#line 4331 "seclang-parser.cc" break; case 281: // var: VARIABLE_MULTIPART_DATA_BEFORE -#line 2354 "seclang-parser.yy" +#line 2357 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartDateBefore()); } -#line 4336 "seclang-parser.cc" +#line 4339 "seclang-parser.cc" break; case 282: // var: "MULTIPART_FILE_LIMIT_EXCEEDED" -#line 2358 "seclang-parser.yy" +#line 2361 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartFileLimitExceeded()); } -#line 4344 "seclang-parser.cc" +#line 4347 "seclang-parser.cc" break; case 283: // var: "MULTIPART_HEADER_FOLDING" -#line 2362 "seclang-parser.yy" +#line 2365 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartHeaderFolding()); } -#line 4352 "seclang-parser.cc" +#line 4355 "seclang-parser.cc" break; case 284: // var: "MULTIPART_INVALID_HEADER_FOLDING" -#line 2366 "seclang-parser.yy" +#line 2369 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidHeaderFolding()); } -#line 4360 "seclang-parser.cc" +#line 4363 "seclang-parser.cc" break; case 285: // var: VARIABLE_MULTIPART_INVALID_PART -#line 2370 "seclang-parser.yy" +#line 2373 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidPart()); } -#line 4368 "seclang-parser.cc" +#line 4371 "seclang-parser.cc" break; case 286: // var: "MULTIPART_INVALID_QUOTING" -#line 2374 "seclang-parser.yy" +#line 2377 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidQuoting()); } -#line 4376 "seclang-parser.cc" +#line 4379 "seclang-parser.cc" break; case 287: // var: VARIABLE_MULTIPART_LF_LINE -#line 2378 "seclang-parser.yy" +#line 2381 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartLFLine()); } -#line 4384 "seclang-parser.cc" +#line 4387 "seclang-parser.cc" break; case 288: // var: VARIABLE_MULTIPART_MISSING_SEMICOLON -#line 2382 "seclang-parser.yy" +#line 2385 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartMissingSemicolon()); } -#line 4392 "seclang-parser.cc" +#line 4395 "seclang-parser.cc" break; case 289: // var: VARIABLE_MULTIPART_SEMICOLON_MISSING -#line 2386 "seclang-parser.yy" +#line 2389 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartMissingSemicolon()); } -#line 4400 "seclang-parser.cc" +#line 4403 "seclang-parser.cc" break; case 290: // var: "MULTIPART_STRICT_ERROR" -#line 2390 "seclang-parser.yy" +#line 2393 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartStrictError()); } -#line 4408 "seclang-parser.cc" +#line 4411 "seclang-parser.cc" break; case 291: // var: "MULTIPART_UNMATCHED_BOUNDARY" -#line 2394 "seclang-parser.yy" +#line 2397 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartUnmatchedBoundary()); } -#line 4416 "seclang-parser.cc" +#line 4419 "seclang-parser.cc" break; case 292: // var: "OUTBOUND_DATA_ERROR" -#line 2398 "seclang-parser.yy" +#line 2401 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::OutboundDataError()); } -#line 4424 "seclang-parser.cc" +#line 4427 "seclang-parser.cc" break; case 293: // var: "PATH_INFO" -#line 2402 "seclang-parser.yy" +#line 2405 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::PathInfo()); } -#line 4432 "seclang-parser.cc" +#line 4435 "seclang-parser.cc" break; case 294: // var: "QUERY_STRING" -#line 2406 "seclang-parser.yy" +#line 2409 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::QueryString()); } -#line 4440 "seclang-parser.cc" +#line 4443 "seclang-parser.cc" break; case 295: // var: "REMOTE_ADDR" -#line 2410 "seclang-parser.yy" +#line 2413 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemoteAddr()); } -#line 4448 "seclang-parser.cc" +#line 4451 "seclang-parser.cc" break; case 296: // var: "REMOTE_HOST" -#line 2414 "seclang-parser.yy" +#line 2417 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemoteHost()); } -#line 4456 "seclang-parser.cc" +#line 4459 "seclang-parser.cc" break; case 297: // var: "REMOTE_PORT" -#line 2418 "seclang-parser.yy" +#line 2421 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemotePort()); } -#line 4464 "seclang-parser.cc" +#line 4467 "seclang-parser.cc" break; case 298: // var: "REQBODY_ERROR" -#line 2422 "seclang-parser.yy" +#line 2425 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyError()); } -#line 4472 "seclang-parser.cc" +#line 4475 "seclang-parser.cc" break; case 299: // var: "REQBODY_ERROR_MSG" -#line 2426 "seclang-parser.yy" +#line 2429 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyErrorMsg()); } -#line 4480 "seclang-parser.cc" +#line 4483 "seclang-parser.cc" break; case 300: // var: "REQBODY_PROCESSOR" -#line 2430 "seclang-parser.yy" +#line 2433 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessor()); } -#line 4488 "seclang-parser.cc" +#line 4491 "seclang-parser.cc" break; case 301: // var: "REQBODY_PROCESSOR_ERROR" -#line 2434 "seclang-parser.yy" +#line 2437 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessorError()); } -#line 4496 "seclang-parser.cc" +#line 4499 "seclang-parser.cc" break; case 302: // var: "REQBODY_PROCESSOR_ERROR_MSG" -#line 2438 "seclang-parser.yy" +#line 2441 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessorErrorMsg()); } -#line 4504 "seclang-parser.cc" +#line 4507 "seclang-parser.cc" break; case 303: // var: "REQUEST_BASENAME" -#line 2442 "seclang-parser.yy" +#line 2445 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBasename()); } -#line 4512 "seclang-parser.cc" +#line 4515 "seclang-parser.cc" break; case 304: // var: "REQUEST_BODY" -#line 2446 "seclang-parser.yy" +#line 2449 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBody()); } -#line 4520 "seclang-parser.cc" +#line 4523 "seclang-parser.cc" break; case 305: // var: "REQUEST_BODY_LENGTH" -#line 2450 "seclang-parser.yy" +#line 2453 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBodyLength()); } -#line 4528 "seclang-parser.cc" +#line 4531 "seclang-parser.cc" break; case 306: // var: "REQUEST_FILENAME" -#line 2454 "seclang-parser.yy" +#line 2457 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestFilename()); } -#line 4536 "seclang-parser.cc" +#line 4539 "seclang-parser.cc" break; case 307: // var: "REQUEST_LINE" -#line 2458 "seclang-parser.yy" +#line 2461 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestLine()); } -#line 4544 "seclang-parser.cc" +#line 4547 "seclang-parser.cc" break; case 308: // var: "REQUEST_METHOD" -#line 2462 "seclang-parser.yy" +#line 2465 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestMethod()); } -#line 4552 "seclang-parser.cc" +#line 4555 "seclang-parser.cc" break; case 309: // var: "REQUEST_PROTOCOL" -#line 2466 "seclang-parser.yy" +#line 2469 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestProtocol()); } -#line 4560 "seclang-parser.cc" +#line 4563 "seclang-parser.cc" break; case 310: // var: "REQUEST_URI" -#line 2470 "seclang-parser.yy" +#line 2473 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestURI()); } -#line 4568 "seclang-parser.cc" +#line 4571 "seclang-parser.cc" break; case 311: // var: "REQUEST_URI_RAW" -#line 2474 "seclang-parser.yy" +#line 2477 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestURIRaw()); } -#line 4576 "seclang-parser.cc" +#line 4579 "seclang-parser.cc" break; case 312: // var: "RESPONSE_BODY" -#line 2478 "seclang-parser.yy" +#line 2481 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseBody()); } -#line 4584 "seclang-parser.cc" +#line 4587 "seclang-parser.cc" break; case 313: // var: "RESPONSE_CONTENT_LENGTH" -#line 2482 "seclang-parser.yy" +#line 2485 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseContentLength()); } -#line 4592 "seclang-parser.cc" +#line 4595 "seclang-parser.cc" break; case 314: // var: "RESPONSE_PROTOCOL" -#line 2486 "seclang-parser.yy" +#line 2489 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseProtocol()); } -#line 4600 "seclang-parser.cc" +#line 4603 "seclang-parser.cc" break; case 315: // var: "RESPONSE_STATUS" -#line 2490 "seclang-parser.yy" +#line 2493 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseStatus()); } -#line 4608 "seclang-parser.cc" +#line 4611 "seclang-parser.cc" break; case 316: // var: "SERVER_ADDR" -#line 2494 "seclang-parser.yy" +#line 2497 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerAddr()); } -#line 4616 "seclang-parser.cc" +#line 4619 "seclang-parser.cc" break; case 317: // var: "SERVER_NAME" -#line 2498 "seclang-parser.yy" +#line 2501 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerName()); } -#line 4624 "seclang-parser.cc" +#line 4627 "seclang-parser.cc" break; case 318: // var: "SERVER_PORT" -#line 2502 "seclang-parser.yy" +#line 2505 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerPort()); } -#line 4632 "seclang-parser.cc" +#line 4635 "seclang-parser.cc" break; case 319: // var: "SESSIONID" -#line 2506 "seclang-parser.yy" +#line 2509 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::SessionID()); } -#line 4640 "seclang-parser.cc" +#line 4643 "seclang-parser.cc" break; case 320: // var: "UNIQUE_ID" -#line 2510 "seclang-parser.yy" +#line 2513 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UniqueID()); } -#line 4648 "seclang-parser.cc" +#line 4651 "seclang-parser.cc" break; case 321: // var: "URLENCODED_ERROR" -#line 2514 "seclang-parser.yy" +#line 2517 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UrlEncodedError()); } -#line 4656 "seclang-parser.cc" +#line 4659 "seclang-parser.cc" break; case 322: // var: "USERID" -#line 2518 "seclang-parser.yy" +#line 2521 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UserID()); } -#line 4664 "seclang-parser.cc" +#line 4667 "seclang-parser.cc" break; case 323: // var: "VARIABLE_STATUS" -#line 2522 "seclang-parser.yy" +#line 2525 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Status()); } -#line 4672 "seclang-parser.cc" +#line 4675 "seclang-parser.cc" break; case 324: // var: "VARIABLE_STATUS_LINE" -#line 2526 "seclang-parser.yy" +#line 2529 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Status()); } -#line 4680 "seclang-parser.cc" +#line 4683 "seclang-parser.cc" break; case 325: // var: "WEBAPPID" -#line 2530 "seclang-parser.yy" +#line 2533 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::WebAppId()); } -#line 4688 "seclang-parser.cc" +#line 4691 "seclang-parser.cc" break; case 326: // var: "RUN_TIME_VAR_DUR" -#line 2534 "seclang-parser.yy" +#line 2537 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new Duration(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4699 "seclang-parser.cc" +#line 4702 "seclang-parser.cc" break; case 327: // var: "RUN_TIME_VAR_BLD" -#line 2542 "seclang-parser.yy" +#line 2545 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new ModsecBuild(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4710 "seclang-parser.cc" +#line 4713 "seclang-parser.cc" break; case 328: // var: "RUN_TIME_VAR_HSV" -#line 2549 "seclang-parser.yy" +#line 2552 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new HighestSeverity(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4721 "seclang-parser.cc" +#line 4724 "seclang-parser.cc" break; case 329: // var: "RUN_TIME_VAR_REMOTE_USER" -#line 2556 "seclang-parser.yy" +#line 2559 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new RemoteUser(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4732 "seclang-parser.cc" +#line 4735 "seclang-parser.cc" break; case 330: // var: "RUN_TIME_VAR_TIME" -#line 2563 "seclang-parser.yy" +#line 2566 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new Time(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4743 "seclang-parser.cc" +#line 4746 "seclang-parser.cc" break; case 331: // var: "RUN_TIME_VAR_TIME_DAY" -#line 2570 "seclang-parser.yy" +#line 2573 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeDay(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4754 "seclang-parser.cc" +#line 4757 "seclang-parser.cc" break; case 332: // var: "RUN_TIME_VAR_TIME_EPOCH" -#line 2577 "seclang-parser.yy" +#line 2580 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeEpoch(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4765 "seclang-parser.cc" +#line 4768 "seclang-parser.cc" break; case 333: // var: "RUN_TIME_VAR_TIME_HOUR" -#line 2584 "seclang-parser.yy" +#line 2587 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeHour(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4776 "seclang-parser.cc" +#line 4779 "seclang-parser.cc" break; case 334: // var: "RUN_TIME_VAR_TIME_MIN" -#line 2591 "seclang-parser.yy" +#line 2594 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeMin(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4787 "seclang-parser.cc" +#line 4790 "seclang-parser.cc" break; case 335: // var: "RUN_TIME_VAR_TIME_MON" -#line 2598 "seclang-parser.yy" +#line 2601 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeMon(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4798 "seclang-parser.cc" +#line 4801 "seclang-parser.cc" break; case 336: // var: "RUN_TIME_VAR_TIME_SEC" -#line 2605 "seclang-parser.yy" +#line 2608 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeSec(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4809 "seclang-parser.cc" +#line 4812 "seclang-parser.cc" break; case 337: // var: "RUN_TIME_VAR_TIME_WDAY" -#line 2612 "seclang-parser.yy" +#line 2615 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeWDay(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4820 "seclang-parser.cc" +#line 4823 "seclang-parser.cc" break; case 338: // var: "RUN_TIME_VAR_TIME_YEAR" -#line 2619 "seclang-parser.yy" +#line 2622 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeYear(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4831 "seclang-parser.cc" +#line 4834 "seclang-parser.cc" break; case 339: // act: "Accuracy" -#line 2629 "seclang-parser.yy" +#line 2632 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Accuracy(yystack_[0].value.as < std::string > ())); } -#line 4839 "seclang-parser.cc" +#line 4842 "seclang-parser.cc" break; case 340: // act: "Allow" -#line 2633 "seclang-parser.yy" +#line 2636 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Allow(yystack_[0].value.as < std::string > ())); } -#line 4847 "seclang-parser.cc" +#line 4850 "seclang-parser.cc" break; case 341: // act: "Append" -#line 2637 "seclang-parser.yy" +#line 2640 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Append", yystack_[1].location); } -#line 4855 "seclang-parser.cc" +#line 4858 "seclang-parser.cc" break; case 342: // act: "AuditLog" -#line 2641 "seclang-parser.yy" +#line 2644 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::AuditLog(yystack_[0].value.as < std::string > ())); } -#line 4863 "seclang-parser.cc" +#line 4866 "seclang-parser.cc" break; case 343: // act: "Block" -#line 2645 "seclang-parser.yy" +#line 2648 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Block(yystack_[0].value.as < std::string > ())); } -#line 4871 "seclang-parser.cc" +#line 4874 "seclang-parser.cc" break; case 344: // act: "Capture" -#line 2649 "seclang-parser.yy" +#line 2652 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Capture(yystack_[0].value.as < std::string > ())); } -#line 4879 "seclang-parser.cc" +#line 4882 "seclang-parser.cc" break; case 345: // act: "Chain" -#line 2653 "seclang-parser.yy" +#line 2656 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Chain(yystack_[0].value.as < std::string > ())); } -#line 4887 "seclang-parser.cc" +#line 4890 "seclang-parser.cc" break; case 346: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_ON" -#line 2657 "seclang-parser.yy" +#line 2660 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditEngine("ctl:auditengine=on")); driver.m_auditLog->setCtlAuditEngineActive(); } -#line 4896 "seclang-parser.cc" +#line 4899 "seclang-parser.cc" break; case 347: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_OFF" -#line 2662 "seclang-parser.yy" +#line 2665 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditEngine("ctl:auditengine=off")); } -#line 4904 "seclang-parser.cc" +#line 4907 "seclang-parser.cc" break; case 348: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_RELEVANT_ONLY" -#line 2666 "seclang-parser.yy" +#line 2669 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditEngine("ctl:auditengine=relevantonly")); driver.m_auditLog->setCtlAuditEngineActive(); } -#line 4913 "seclang-parser.cc" +#line 4916 "seclang-parser.cc" break; case 349: // act: "ACTION_CTL_AUDIT_LOG_PARTS" -#line 2671 "seclang-parser.yy" +#line 2674 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditLogParts(yystack_[0].value.as < std::string > ())); } -#line 4921 "seclang-parser.cc" +#line 4924 "seclang-parser.cc" break; case 350: // act: "ACTION_CTL_BDY_JSON" -#line 2675 "seclang-parser.yy" +#line 2678 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorJSON(yystack_[0].value.as < std::string > ())); } -#line 4929 "seclang-parser.cc" +#line 4932 "seclang-parser.cc" break; case 351: // act: "ACTION_CTL_BDY_XML" -#line 2679 "seclang-parser.yy" +#line 2682 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorXML(yystack_[0].value.as < std::string > ())); } -#line 4937 "seclang-parser.cc" +#line 4940 "seclang-parser.cc" break; case 352: // act: "ACTION_CTL_BDY_URLENCODED" -#line 2683 "seclang-parser.yy" +#line 2686 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorURLENCODED(yystack_[0].value.as < std::string > ())); } -#line 4945 "seclang-parser.cc" +#line 4948 "seclang-parser.cc" break; case 353: // act: "ACTION_CTL_FORCE_REQ_BODY_VAR" "CONFIG_VALUE_ON" -#line 2687 "seclang-parser.yy" +#line 2690 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4954 "seclang-parser.cc" +#line 4957 "seclang-parser.cc" break; case 354: // act: "ACTION_CTL_FORCE_REQ_BODY_VAR" "CONFIG_VALUE_OFF" -#line 2692 "seclang-parser.yy" +#line 2695 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4963 "seclang-parser.cc" +#line 4966 "seclang-parser.cc" break; case 355: // act: "ACTION_CTL_REQUEST_BODY_ACCESS" "CONFIG_VALUE_ON" -#line 2697 "seclang-parser.yy" +#line 2700 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyAccess(yystack_[1].value.as < std::string > () + "true")); } -#line 4971 "seclang-parser.cc" +#line 4974 "seclang-parser.cc" break; case 356: // act: "ACTION_CTL_REQUEST_BODY_ACCESS" "CONFIG_VALUE_OFF" -#line 2701 "seclang-parser.yy" +#line 2704 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyAccess(yystack_[1].value.as < std::string > () + "false")); } -#line 4979 "seclang-parser.cc" +#line 4982 "seclang-parser.cc" break; case 357: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_ON" -#line 2705 "seclang-parser.yy" +#line 2708 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=on")); } -#line 4987 "seclang-parser.cc" +#line 4990 "seclang-parser.cc" break; case 358: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_OFF" -#line 2709 "seclang-parser.yy" +#line 2712 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=off")); } -#line 4995 "seclang-parser.cc" +#line 4998 "seclang-parser.cc" break; case 359: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_DETC" -#line 2713 "seclang-parser.yy" +#line 2716 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=detectiononly")); } -#line 5003 "seclang-parser.cc" +#line 5006 "seclang-parser.cc" break; case 360: // act: "ACTION_CTL_RULE_REMOVE_BY_ID" -#line 2717 "seclang-parser.yy" +#line 2720 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveById(yystack_[0].value.as < std::string > ())); } -#line 5011 "seclang-parser.cc" +#line 5014 "seclang-parser.cc" break; case 361: // act: "ACTION_CTL_RULE_REMOVE_BY_TAG" -#line 2721 "seclang-parser.yy" +#line 2724 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveByTag(yystack_[0].value.as < std::string > ())); } -#line 5019 "seclang-parser.cc" +#line 5022 "seclang-parser.cc" break; case 362: // act: "ACTION_CTL_RULE_REMOVE_TARGET_BY_ID" -#line 2725 "seclang-parser.yy" +#line 2728 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveTargetById(yystack_[0].value.as < std::string > ())); } -#line 5027 "seclang-parser.cc" +#line 5030 "seclang-parser.cc" break; case 363: // act: "ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG" -#line 2729 "seclang-parser.yy" +#line 2732 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveTargetByTag(yystack_[0].value.as < std::string > ())); } -#line 5035 "seclang-parser.cc" +#line 5038 "seclang-parser.cc" break; case 364: // act: "Deny" -#line 2733 "seclang-parser.yy" +#line 2736 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Deny(yystack_[0].value.as < std::string > ())); } -#line 5043 "seclang-parser.cc" +#line 5046 "seclang-parser.cc" break; case 365: // act: "DeprecateVar" -#line 2737 "seclang-parser.yy" +#line 2740 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("DeprecateVar", yystack_[1].location); } -#line 5051 "seclang-parser.cc" +#line 5054 "seclang-parser.cc" break; case 366: // act: "Drop" -#line 2741 "seclang-parser.yy" +#line 2744 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Drop(yystack_[0].value.as < std::string > ())); } -#line 5059 "seclang-parser.cc" +#line 5062 "seclang-parser.cc" break; case 367: // act: "Exec" -#line 2745 "seclang-parser.yy" +#line 2748 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Exec(yystack_[0].value.as < std::string > ())); } -#line 5067 "seclang-parser.cc" +#line 5070 "seclang-parser.cc" break; case 368: // act: "ExpireVar" run_time_string -#line 2749 "seclang-parser.yy" +#line 2752 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ExpireVar(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5075 "seclang-parser.cc" +#line 5078 "seclang-parser.cc" break; case 369: // act: "Id" -#line 2753 "seclang-parser.yy" +#line 2756 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::RuleId(yystack_[0].value.as < std::string > ())); } -#line 5083 "seclang-parser.cc" +#line 5086 "seclang-parser.cc" break; case 370: // act: "InitCol" run_time_string -#line 2757 "seclang-parser.yy" +#line 2760 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::InitCol(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5091 "seclang-parser.cc" +#line 5094 "seclang-parser.cc" break; case 371: // act: "LogData" run_time_string -#line 2761 "seclang-parser.yy" +#line 2764 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::LogData(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5099 "seclang-parser.cc" +#line 5102 "seclang-parser.cc" break; case 372: // act: "Log" -#line 2765 "seclang-parser.yy" +#line 2768 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Log(yystack_[0].value.as < std::string > ())); } -#line 5107 "seclang-parser.cc" +#line 5110 "seclang-parser.cc" break; case 373: // act: "Maturity" -#line 2769 "seclang-parser.yy" +#line 2772 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Maturity(yystack_[0].value.as < std::string > ())); } -#line 5115 "seclang-parser.cc" +#line 5118 "seclang-parser.cc" break; case 374: // act: "Msg" run_time_string -#line 2773 "seclang-parser.yy" +#line 2776 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Msg(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5123 "seclang-parser.cc" +#line 5126 "seclang-parser.cc" break; case 375: // act: "MultiMatch" -#line 2777 "seclang-parser.yy" +#line 2780 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::MultiMatch(yystack_[0].value.as < std::string > ())); } -#line 5131 "seclang-parser.cc" +#line 5134 "seclang-parser.cc" break; case 376: // act: "NoAuditLog" -#line 2781 "seclang-parser.yy" +#line 2784 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoAuditLog(yystack_[0].value.as < std::string > ())); } -#line 5139 "seclang-parser.cc" +#line 5142 "seclang-parser.cc" break; case 377: // act: "NoLog" -#line 2785 "seclang-parser.yy" +#line 2788 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoLog(yystack_[0].value.as < std::string > ())); } -#line 5147 "seclang-parser.cc" +#line 5150 "seclang-parser.cc" break; case 378: // act: "Pass" -#line 2789 "seclang-parser.yy" +#line 2792 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Pass(yystack_[0].value.as < std::string > ())); } -#line 5155 "seclang-parser.cc" +#line 5158 "seclang-parser.cc" break; case 379: // act: "Pause" -#line 2793 "seclang-parser.yy" +#line 2796 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Pause", yystack_[1].location); } -#line 5163 "seclang-parser.cc" +#line 5166 "seclang-parser.cc" break; case 380: // act: "Phase" -#line 2797 "seclang-parser.yy" +#line 2800 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Phase(yystack_[0].value.as < std::string > ())); } -#line 5171 "seclang-parser.cc" +#line 5174 "seclang-parser.cc" break; case 381: // act: "Prepend" -#line 2801 "seclang-parser.yy" +#line 2804 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Prepend", yystack_[1].location); } -#line 5179 "seclang-parser.cc" +#line 5182 "seclang-parser.cc" break; case 382: // act: "Proxy" -#line 2805 "seclang-parser.yy" +#line 2808 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Proxy", yystack_[1].location); } -#line 5187 "seclang-parser.cc" +#line 5190 "seclang-parser.cc" break; case 383: // act: "Redirect" run_time_string -#line 2809 "seclang-parser.yy" +#line 2812 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Redirect(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5195 "seclang-parser.cc" +#line 5198 "seclang-parser.cc" break; case 384: // act: "Rev" -#line 2813 "seclang-parser.yy" +#line 2816 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Rev(yystack_[0].value.as < std::string > ())); } -#line 5203 "seclang-parser.cc" +#line 5206 "seclang-parser.cc" break; case 385: // act: "SanitiseArg" -#line 2817 "seclang-parser.yy" +#line 2820 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseArg", yystack_[1].location); } -#line 5211 "seclang-parser.cc" +#line 5214 "seclang-parser.cc" break; case 386: // act: "SanitiseMatched" -#line 2821 "seclang-parser.yy" +#line 2824 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseMatched", yystack_[1].location); } -#line 5219 "seclang-parser.cc" +#line 5222 "seclang-parser.cc" break; case 387: // act: "SanitiseMatchedBytes" -#line 2825 "seclang-parser.yy" +#line 2828 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseMatchedBytes", yystack_[1].location); } -#line 5227 "seclang-parser.cc" +#line 5230 "seclang-parser.cc" break; case 388: // act: "SanitiseRequestHeader" -#line 2829 "seclang-parser.yy" +#line 2832 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseRequestHeader", yystack_[1].location); } -#line 5235 "seclang-parser.cc" +#line 5238 "seclang-parser.cc" break; case 389: // act: "SanitiseResponseHeader" -#line 2833 "seclang-parser.yy" +#line 2836 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseResponseHeader", yystack_[1].location); } -#line 5243 "seclang-parser.cc" +#line 5246 "seclang-parser.cc" break; case 390: // act: "SetEnv" run_time_string -#line 2837 "seclang-parser.yy" +#line 2840 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetENV(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5251 "seclang-parser.cc" +#line 5254 "seclang-parser.cc" break; case 391: // act: "SetRsc" run_time_string -#line 2841 "seclang-parser.yy" +#line 2844 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetRSC(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5259 "seclang-parser.cc" +#line 5262 "seclang-parser.cc" break; case 392: // act: "SetSid" run_time_string -#line 2845 "seclang-parser.yy" +#line 2848 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetSID(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5267 "seclang-parser.cc" +#line 5270 "seclang-parser.cc" break; case 393: // act: "SetUID" run_time_string -#line 2849 "seclang-parser.yy" +#line 2852 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetUID(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5275 "seclang-parser.cc" +#line 5278 "seclang-parser.cc" break; case 394: // act: "SetVar" setvar_action -#line 2853 "seclang-parser.yy" +#line 2856 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > () = std::move(yystack_[0].value.as < std::unique_ptr > ()); } -#line 5283 "seclang-parser.cc" +#line 5286 "seclang-parser.cc" break; case 395: // act: "Severity" -#line 2857 "seclang-parser.yy" +#line 2860 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Severity(yystack_[0].value.as < std::string > ())); } -#line 5291 "seclang-parser.cc" +#line 5294 "seclang-parser.cc" break; case 396: // act: "Skip" -#line 2861 "seclang-parser.yy" +#line 2864 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Skip(yystack_[0].value.as < std::string > ())); } -#line 5299 "seclang-parser.cc" +#line 5302 "seclang-parser.cc" break; case 397: // act: "SkipAfter" -#line 2865 "seclang-parser.yy" +#line 2868 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SkipAfter(yystack_[0].value.as < std::string > ())); } -#line 5307 "seclang-parser.cc" +#line 5310 "seclang-parser.cc" break; case 398: // act: "Status" -#line 2869 "seclang-parser.yy" +#line 2872 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::data::Status(yystack_[0].value.as < std::string > ())); } -#line 5315 "seclang-parser.cc" +#line 5318 "seclang-parser.cc" break; case 399: // act: "Tag" run_time_string -#line 2873 "seclang-parser.yy" +#line 2876 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Tag(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5323 "seclang-parser.cc" +#line 5326 "seclang-parser.cc" break; case 400: // act: "Ver" -#line 2877 "seclang-parser.yy" +#line 2880 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Ver(yystack_[0].value.as < std::string > ())); } -#line 5331 "seclang-parser.cc" +#line 5334 "seclang-parser.cc" break; case 401: // act: "xmlns" -#line 2881 "seclang-parser.yy" +#line 2884 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::XmlNS(yystack_[0].value.as < std::string > ())); } -#line 5339 "seclang-parser.cc" +#line 5342 "seclang-parser.cc" break; case 402: // act: "ACTION_TRANSFORMATION_PARITY_ZERO_7_BIT" -#line 2885 "seclang-parser.yy" +#line 2888 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityZero7bit(yystack_[0].value.as < std::string > ())); } -#line 5347 "seclang-parser.cc" +#line 5350 "seclang-parser.cc" break; case 403: // act: "ACTION_TRANSFORMATION_PARITY_ODD_7_BIT" -#line 2889 "seclang-parser.yy" +#line 2892 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityOdd7bit(yystack_[0].value.as < std::string > ())); } -#line 5355 "seclang-parser.cc" +#line 5358 "seclang-parser.cc" break; case 404: // act: "ACTION_TRANSFORMATION_PARITY_EVEN_7_BIT" -#line 2893 "seclang-parser.yy" +#line 2896 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityEven7bit(yystack_[0].value.as < std::string > ())); } -#line 5363 "seclang-parser.cc" +#line 5366 "seclang-parser.cc" break; case 405: // act: "ACTION_TRANSFORMATION_SQL_HEX_DECODE" -#line 2897 "seclang-parser.yy" +#line 2900 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::SqlHexDecode(yystack_[0].value.as < std::string > ())); } -#line 5371 "seclang-parser.cc" +#line 5374 "seclang-parser.cc" break; case 406: // act: "ACTION_TRANSFORMATION_BASE_64_ENCODE" -#line 2901 "seclang-parser.yy" +#line 2904 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Encode(yystack_[0].value.as < std::string > ())); } -#line 5379 "seclang-parser.cc" +#line 5382 "seclang-parser.cc" break; case 407: // act: "ACTION_TRANSFORMATION_BASE_64_DECODE" -#line 2905 "seclang-parser.yy" +#line 2908 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Decode(yystack_[0].value.as < std::string > ())); } -#line 5387 "seclang-parser.cc" +#line 5390 "seclang-parser.cc" break; case 408: // act: "ACTION_TRANSFORMATION_BASE_64_DECODE_EXT" -#line 2909 "seclang-parser.yy" +#line 2912 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64DecodeExt(yystack_[0].value.as < std::string > ())); } -#line 5395 "seclang-parser.cc" +#line 5398 "seclang-parser.cc" break; case 409: // act: "ACTION_TRANSFORMATION_CMD_LINE" -#line 2913 "seclang-parser.yy" +#line 2916 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CmdLine(yystack_[0].value.as < std::string > ())); } -#line 5403 "seclang-parser.cc" +#line 5406 "seclang-parser.cc" break; case 410: // act: "ACTION_TRANSFORMATION_SHA1" -#line 2917 "seclang-parser.yy" +#line 2920 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Sha1(yystack_[0].value.as < std::string > ())); } -#line 5411 "seclang-parser.cc" +#line 5414 "seclang-parser.cc" break; case 411: // act: "ACTION_TRANSFORMATION_MD5" -#line 2921 "seclang-parser.yy" +#line 2924 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Md5(yystack_[0].value.as < std::string > ())); } -#line 5419 "seclang-parser.cc" +#line 5422 "seclang-parser.cc" break; case 412: // act: "ACTION_TRANSFORMATION_ESCAPE_SEQ_DECODE" -#line 2925 "seclang-parser.yy" +#line 2928 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::EscapeSeqDecode(yystack_[0].value.as < std::string > ())); } -#line 5427 "seclang-parser.cc" +#line 5430 "seclang-parser.cc" break; case 413: // act: "ACTION_TRANSFORMATION_HEX_ENCODE" -#line 2929 "seclang-parser.yy" +#line 2932 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexEncode(yystack_[0].value.as < std::string > ())); } -#line 5435 "seclang-parser.cc" +#line 5438 "seclang-parser.cc" break; case 414: // act: "ACTION_TRANSFORMATION_HEX_DECODE" -#line 2933 "seclang-parser.yy" +#line 2936 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexDecode(yystack_[0].value.as < std::string > ())); } -#line 5443 "seclang-parser.cc" +#line 5446 "seclang-parser.cc" break; case 415: // act: "ACTION_TRANSFORMATION_LOWERCASE" -#line 2937 "seclang-parser.yy" +#line 2940 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::LowerCase(yystack_[0].value.as < std::string > ())); } -#line 5451 "seclang-parser.cc" +#line 5454 "seclang-parser.cc" break; case 416: // act: "ACTION_TRANSFORMATION_UPPERCASE" -#line 2941 "seclang-parser.yy" +#line 2944 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UpperCase(yystack_[0].value.as < std::string > ())); } -#line 5459 "seclang-parser.cc" +#line 5462 "seclang-parser.cc" break; case 417: // act: "ACTION_TRANSFORMATION_URL_DECODE_UNI" -#line 2945 "seclang-parser.yy" +#line 2948 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecodeUni(yystack_[0].value.as < std::string > ())); } -#line 5467 "seclang-parser.cc" +#line 5470 "seclang-parser.cc" break; case 418: // act: "ACTION_TRANSFORMATION_URL_DECODE" -#line 2949 "seclang-parser.yy" +#line 2952 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecode(yystack_[0].value.as < std::string > ())); } -#line 5475 "seclang-parser.cc" +#line 5478 "seclang-parser.cc" break; case 419: // act: "ACTION_TRANSFORMATION_URL_ENCODE" -#line 2953 "seclang-parser.yy" +#line 2956 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlEncode(yystack_[0].value.as < std::string > ())); } -#line 5483 "seclang-parser.cc" +#line 5486 "seclang-parser.cc" break; case 420: // act: "ACTION_TRANSFORMATION_NONE" -#line 2957 "seclang-parser.yy" +#line 2960 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::None(yystack_[0].value.as < std::string > ())); } -#line 5491 "seclang-parser.cc" +#line 5494 "seclang-parser.cc" break; case 421: // act: "ACTION_TRANSFORMATION_COMPRESS_WHITESPACE" -#line 2961 "seclang-parser.yy" +#line 2964 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CompressWhitespace(yystack_[0].value.as < std::string > ())); } -#line 5499 "seclang-parser.cc" +#line 5502 "seclang-parser.cc" break; case 422: // act: "ACTION_TRANSFORMATION_REMOVE_WHITESPACE" -#line 2965 "seclang-parser.yy" +#line 2968 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveWhitespace(yystack_[0].value.as < std::string > ())); } -#line 5507 "seclang-parser.cc" +#line 5510 "seclang-parser.cc" break; case 423: // act: "ACTION_TRANSFORMATION_REPLACE_NULLS" -#line 2969 "seclang-parser.yy" +#line 2972 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceNulls(yystack_[0].value.as < std::string > ())); } -#line 5515 "seclang-parser.cc" +#line 5518 "seclang-parser.cc" break; case 424: // act: "ACTION_TRANSFORMATION_REMOVE_NULLS" -#line 2973 "seclang-parser.yy" +#line 2976 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveNulls(yystack_[0].value.as < std::string > ())); } -#line 5523 "seclang-parser.cc" +#line 5526 "seclang-parser.cc" break; case 425: // act: "ACTION_TRANSFORMATION_HTML_ENTITY_DECODE" -#line 2977 "seclang-parser.yy" +#line 2980 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HtmlEntityDecode(yystack_[0].value.as < std::string > ())); } -#line 5531 "seclang-parser.cc" +#line 5534 "seclang-parser.cc" break; case 426: // act: "ACTION_TRANSFORMATION_JS_DECODE" -#line 2981 "seclang-parser.yy" +#line 2984 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::JsDecode(yystack_[0].value.as < std::string > ())); } -#line 5539 "seclang-parser.cc" +#line 5542 "seclang-parser.cc" break; case 427: // act: "ACTION_TRANSFORMATION_CSS_DECODE" -#line 2985 "seclang-parser.yy" +#line 2988 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CssDecode(yystack_[0].value.as < std::string > ())); } -#line 5547 "seclang-parser.cc" +#line 5550 "seclang-parser.cc" break; case 428: // act: "ACTION_TRANSFORMATION_TRIM" -#line 2989 "seclang-parser.yy" +#line 2992 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Trim(yystack_[0].value.as < std::string > ())); } -#line 5555 "seclang-parser.cc" +#line 5558 "seclang-parser.cc" break; case 429: // act: "ACTION_TRANSFORMATION_TRIM_LEFT" -#line 2993 "seclang-parser.yy" +#line 2996 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimLeft(yystack_[0].value.as < std::string > ())); } -#line 5563 "seclang-parser.cc" +#line 5566 "seclang-parser.cc" break; case 430: // act: "ACTION_TRANSFORMATION_TRIM_RIGHT" -#line 2997 "seclang-parser.yy" +#line 3000 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimRight(yystack_[0].value.as < std::string > ())); } -#line 5571 "seclang-parser.cc" +#line 5574 "seclang-parser.cc" break; case 431: // act: "ACTION_TRANSFORMATION_NORMALISE_PATH_WIN" -#line 3001 "seclang-parser.yy" +#line 3004 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePathWin(yystack_[0].value.as < std::string > ())); } -#line 5579 "seclang-parser.cc" +#line 5582 "seclang-parser.cc" break; case 432: // act: "ACTION_TRANSFORMATION_NORMALISE_PATH" -#line 3005 "seclang-parser.yy" +#line 3008 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePath(yystack_[0].value.as < std::string > ())); } -#line 5587 "seclang-parser.cc" +#line 5590 "seclang-parser.cc" break; case 433: // act: "ACTION_TRANSFORMATION_LENGTH" -#line 3009 "seclang-parser.yy" +#line 3012 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Length(yystack_[0].value.as < std::string > ())); } -#line 5595 "seclang-parser.cc" +#line 5598 "seclang-parser.cc" break; case 434: // act: "ACTION_TRANSFORMATION_UTF8_TO_UNICODE" -#line 3013 "seclang-parser.yy" +#line 3016 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Utf8ToUnicode(yystack_[0].value.as < std::string > ())); } -#line 5603 "seclang-parser.cc" +#line 5606 "seclang-parser.cc" break; case 435: // act: "ACTION_TRANSFORMATION_REMOVE_COMMENTS_CHAR" -#line 3017 "seclang-parser.yy" +#line 3020 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveCommentsChar(yystack_[0].value.as < std::string > ())); } -#line 5611 "seclang-parser.cc" +#line 5614 "seclang-parser.cc" break; case 436: // act: "ACTION_TRANSFORMATION_REMOVE_COMMENTS" -#line 3021 "seclang-parser.yy" +#line 3024 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveComments(yystack_[0].value.as < std::string > ())); } -#line 5619 "seclang-parser.cc" +#line 5622 "seclang-parser.cc" break; case 437: // act: "ACTION_TRANSFORMATION_REPLACE_COMMENTS" -#line 3025 "seclang-parser.yy" +#line 3028 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceComments(yystack_[0].value.as < std::string > ())); } -#line 5627 "seclang-parser.cc" +#line 5630 "seclang-parser.cc" break; case 438: // setvar_action: "NOT" var -#line 3032 "seclang-parser.yy" +#line 3035 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::unsetOperation, std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5635 "seclang-parser.cc" +#line 5638 "seclang-parser.cc" break; case 439: // setvar_action: var -#line 3036 "seclang-parser.yy" +#line 3039 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::setToOneOperation, std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5643 "seclang-parser.cc" +#line 5646 "seclang-parser.cc" break; case 440: // setvar_action: var SETVAR_OPERATION_EQUALS run_time_string -#line 3040 "seclang-parser.yy" +#line 3043 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::setOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5651 "seclang-parser.cc" +#line 5654 "seclang-parser.cc" break; case 441: // setvar_action: var SETVAR_OPERATION_EQUALS_PLUS run_time_string -#line 3044 "seclang-parser.yy" +#line 3047 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::sumAndSetOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5659 "seclang-parser.cc" +#line 5662 "seclang-parser.cc" break; case 442: // setvar_action: var SETVAR_OPERATION_EQUALS_MINUS run_time_string -#line 3048 "seclang-parser.yy" +#line 3051 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::substractAndSetOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5667 "seclang-parser.cc" +#line 5670 "seclang-parser.cc" break; case 443: // run_time_string: run_time_string "FREE_TEXT_QUOTE_MACRO_EXPANSION" -#line 3055 "seclang-parser.yy" +#line 3058 "seclang-parser.yy" { yystack_[1].value.as < std::unique_ptr > ()->appendText(yystack_[0].value.as < std::string > ()); yylhs.value.as < std::unique_ptr > () = std::move(yystack_[1].value.as < std::unique_ptr > ()); } -#line 5676 "seclang-parser.cc" +#line 5679 "seclang-parser.cc" break; case 444: // run_time_string: run_time_string var -#line 3060 "seclang-parser.yy" +#line 3063 "seclang-parser.yy" { yystack_[1].value.as < std::unique_ptr > ()->appendVar(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > () = std::move(yystack_[1].value.as < std::unique_ptr > ()); } -#line 5685 "seclang-parser.cc" +#line 5688 "seclang-parser.cc" break; case 445: // run_time_string: "FREE_TEXT_QUOTE_MACRO_EXPANSION" -#line 3065 "seclang-parser.yy" +#line 3068 "seclang-parser.yy" { std::unique_ptr r(new RunTimeString()); r->appendText(yystack_[0].value.as < std::string > ()); yylhs.value.as < std::unique_ptr > () = std::move(r); } -#line 5695 "seclang-parser.cc" +#line 5698 "seclang-parser.cc" break; case 446: // run_time_string: var -#line 3071 "seclang-parser.yy" +#line 3074 "seclang-parser.yy" { std::unique_ptr r(new RunTimeString()); r->appendVar(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > () = std::move(r); } -#line 5705 "seclang-parser.cc" +#line 5708 "seclang-parser.cc" break; -#line 5709 "seclang-parser.cc" +#line 5712 "seclang-parser.cc" default: break; @@ -7236,44 +7239,44 @@ namespace yy { 934, 938, 942, 946, 950, 954, 958, 963, 967, 971, 975, 979, 983, 988, 993, 997, 1001, 1005, 1009, 1013, 1017, 1021, 1025, 1029, 1033, 1037, 1041, 1045, 1049, 1053, - 1057, 1061, 1065, 1069, 1083, 1084, 1114, 1133, 1152, 1180, - 1237, 1244, 1248, 1252, 1256, 1260, 1264, 1268, 1272, 1281, - 1285, 1290, 1293, 1298, 1303, 1308, 1313, 1316, 1321, 1324, - 1329, 1334, 1337, 1342, 1347, 1352, 1357, 1362, 1367, 1372, - 1375, 1380, 1385, 1390, 1395, 1398, 1403, 1408, 1413, 1426, - 1439, 1452, 1465, 1478, 1504, 1532, 1544, 1564, 1591, 1596, - 1602, 1607, 1612, 1621, 1626, 1630, 1634, 1638, 1642, 1646, - 1650, 1655, 1660, 1672, 1678, 1682, 1686, 1697, 1706, 1707, - 1714, 1719, 1724, 1778, 1785, 1793, 1830, 1834, 1841, 1846, - 1852, 1858, 1864, 1871, 1881, 1885, 1889, 1893, 1897, 1901, - 1905, 1909, 1913, 1917, 1921, 1925, 1929, 1933, 1937, 1941, - 1945, 1949, 1953, 1957, 1961, 1965, 1969, 1973, 1977, 1981, - 1985, 1989, 1993, 1997, 2001, 2005, 2009, 2013, 2017, 2021, - 2025, 2029, 2033, 2037, 2041, 2045, 2049, 2053, 2057, 2061, - 2065, 2069, 2073, 2077, 2081, 2085, 2089, 2093, 2097, 2101, - 2105, 2109, 2113, 2117, 2121, 2125, 2129, 2133, 2137, 2141, - 2145, 2149, 2153, 2157, 2161, 2165, 2169, 2173, 2177, 2181, - 2185, 2189, 2193, 2197, 2201, 2205, 2209, 2213, 2217, 2221, - 2225, 2229, 2233, 2237, 2241, 2245, 2249, 2254, 2258, 2262, - 2267, 2271, 2275, 2280, 2285, 2289, 2293, 2297, 2301, 2305, - 2309, 2313, 2317, 2321, 2325, 2329, 2333, 2337, 2341, 2345, - 2349, 2353, 2357, 2361, 2365, 2369, 2373, 2377, 2381, 2385, - 2389, 2393, 2397, 2401, 2405, 2409, 2413, 2417, 2421, 2425, - 2429, 2433, 2437, 2441, 2445, 2449, 2453, 2457, 2461, 2465, - 2469, 2473, 2477, 2481, 2485, 2489, 2493, 2497, 2501, 2505, - 2509, 2513, 2517, 2521, 2525, 2529, 2533, 2541, 2548, 2555, - 2562, 2569, 2576, 2583, 2590, 2597, 2604, 2611, 2618, 2628, - 2632, 2636, 2640, 2644, 2648, 2652, 2656, 2661, 2665, 2670, - 2674, 2678, 2682, 2686, 2691, 2696, 2700, 2704, 2708, 2712, - 2716, 2720, 2724, 2728, 2732, 2736, 2740, 2744, 2748, 2752, - 2756, 2760, 2764, 2768, 2772, 2776, 2780, 2784, 2788, 2792, - 2796, 2800, 2804, 2808, 2812, 2816, 2820, 2824, 2828, 2832, - 2836, 2840, 2844, 2848, 2852, 2856, 2860, 2864, 2868, 2872, - 2876, 2880, 2884, 2888, 2892, 2896, 2900, 2904, 2908, 2912, - 2916, 2920, 2924, 2928, 2932, 2936, 2940, 2944, 2948, 2952, - 2956, 2960, 2964, 2968, 2972, 2976, 2980, 2984, 2988, 2992, - 2996, 3000, 3004, 3008, 3012, 3016, 3020, 3024, 3031, 3035, - 3039, 3043, 3047, 3054, 3059, 3064, 3070 + 1057, 1061, 1065, 1069, 1083, 1084, 1115, 1134, 1154, 1183, + 1240, 1247, 1251, 1255, 1259, 1263, 1267, 1271, 1275, 1284, + 1288, 1293, 1296, 1301, 1306, 1311, 1316, 1319, 1324, 1327, + 1332, 1337, 1340, 1345, 1350, 1355, 1360, 1365, 1370, 1375, + 1378, 1383, 1388, 1393, 1398, 1401, 1406, 1411, 1416, 1429, + 1442, 1455, 1468, 1481, 1507, 1535, 1547, 1567, 1594, 1599, + 1605, 1610, 1615, 1624, 1629, 1633, 1637, 1641, 1645, 1649, + 1653, 1658, 1663, 1675, 1681, 1685, 1689, 1700, 1709, 1710, + 1717, 1722, 1727, 1781, 1788, 1796, 1833, 1837, 1844, 1849, + 1855, 1861, 1867, 1874, 1884, 1888, 1892, 1896, 1900, 1904, + 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944, + 1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, + 1988, 1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, 2024, + 2028, 2032, 2036, 2040, 2044, 2048, 2052, 2056, 2060, 2064, + 2068, 2072, 2076, 2080, 2084, 2088, 2092, 2096, 2100, 2104, + 2108, 2112, 2116, 2120, 2124, 2128, 2132, 2136, 2140, 2144, + 2148, 2152, 2156, 2160, 2164, 2168, 2172, 2176, 2180, 2184, + 2188, 2192, 2196, 2200, 2204, 2208, 2212, 2216, 2220, 2224, + 2228, 2232, 2236, 2240, 2244, 2248, 2252, 2257, 2261, 2265, + 2270, 2274, 2278, 2283, 2288, 2292, 2296, 2300, 2304, 2308, + 2312, 2316, 2320, 2324, 2328, 2332, 2336, 2340, 2344, 2348, + 2352, 2356, 2360, 2364, 2368, 2372, 2376, 2380, 2384, 2388, + 2392, 2396, 2400, 2404, 2408, 2412, 2416, 2420, 2424, 2428, + 2432, 2436, 2440, 2444, 2448, 2452, 2456, 2460, 2464, 2468, + 2472, 2476, 2480, 2484, 2488, 2492, 2496, 2500, 2504, 2508, + 2512, 2516, 2520, 2524, 2528, 2532, 2536, 2544, 2551, 2558, + 2565, 2572, 2579, 2586, 2593, 2600, 2607, 2614, 2621, 2631, + 2635, 2639, 2643, 2647, 2651, 2655, 2659, 2664, 2668, 2673, + 2677, 2681, 2685, 2689, 2694, 2699, 2703, 2707, 2711, 2715, + 2719, 2723, 2727, 2731, 2735, 2739, 2743, 2747, 2751, 2755, + 2759, 2763, 2767, 2771, 2775, 2779, 2783, 2787, 2791, 2795, + 2799, 2803, 2807, 2811, 2815, 2819, 2823, 2827, 2831, 2835, + 2839, 2843, 2847, 2851, 2855, 2859, 2863, 2867, 2871, 2875, + 2879, 2883, 2887, 2891, 2895, 2899, 2903, 2907, 2911, 2915, + 2919, 2923, 2927, 2931, 2935, 2939, 2943, 2947, 2951, 2955, + 2959, 2963, 2967, 2971, 2975, 2979, 2983, 2987, 2991, 2995, + 2999, 3003, 3007, 3011, 3015, 3019, 3023, 3027, 3034, 3038, + 3042, 3046, 3050, 3057, 3062, 3067, 3073 }; void @@ -7305,9 +7308,9 @@ namespace yy { } // yy -#line 7309 "seclang-parser.cc" +#line 7312 "seclang-parser.cc" -#line 3077 "seclang-parser.yy" +#line 3080 "seclang-parser.yy" void yy::seclang_parser::error (const location_type& l, const std::string& m) { diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 0be74565..f6610951 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -1086,8 +1086,9 @@ expression: std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *$4.get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -1135,8 +1136,9 @@ expression: std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *$2.get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -1155,8 +1157,9 @@ expression: std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *$2.get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index e0804946..e5d8183f 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -99,17 +99,16 @@ RuleWithActions::RuleWithActions( } else if (dynamic_cast(a)) { m_containsMultiMatchAction = true; delete a; - } else if (dynamic_cast(a)) { - m_severity = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_logData = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_msg = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_actionsSetVar.push_back( - dynamic_cast(a)); - } else if (dynamic_cast(a)) { - m_actionsTag.push_back(dynamic_cast(a)); + } else if (auto sa = dynamic_cast(a)) { + m_severity = sa; + } else if (auto lda = dynamic_cast(a)) { + m_logData = lda; + } else if (auto ma = dynamic_cast(a)) { + m_msg = ma; + } else if (auto sva = dynamic_cast(a)) { + m_actionsSetVar.push_back(sva); + } else if (auto ta = dynamic_cast(a)) { + m_actionsTag.push_back(ta); } else if (dynamic_cast(a)) { m_actionsRuntimePos.push_back(a); m_containsStaticBlockAction = true; diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index d63129da..f54ffb5c 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -131,32 +131,15 @@ bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string & } -void RuleWithOperator::getVariablesExceptions(Transaction *t, - variables::Variables *exclusion, variables::Variables *addition) { - for (const auto &[tag, v] : t->m_rules->m_exceptions.m_variable_update_target_by_tag) { // cppcheck-suppress ctunullpointer - if (containsTag(*tag.get(), t)) { - if (Variable *b{v.get()};dynamic_cast(b)) { - exclusion->push_back(dynamic_cast(b)->m_base.get()); - } else { - addition->push_back(b); - } - } - } - - for (const auto &[msg, v] : t->m_rules->m_exceptions.m_variable_update_target_by_msg) { - if (containsMsg(*msg.get(), t)) { - if (Variable *b{v.get()}; dynamic_cast(b)) { - exclusion->push_back(dynamic_cast(b)->m_base.get()); - } else { - addition->push_back(b); - } - } - } - - for (const auto &[id, v] : t->m_rules->m_exceptions.m_variable_update_target_by_id) { // cppcheck-suppress unassignedVariable - if (m_ruleId == id) { - if (Variable *b{v.get()};dynamic_cast(b)) { - exclusion->push_back(dynamic_cast(b)->m_base.get()); +template +void getVariablesExceptionsHelper( + variables::Variables *exclusion, variables::Variables *addition, + const MapType &map, Operation op) { + for (const auto &[x, v] : map) { + if (op(x)) { + auto b = v.get(); + if (auto vme = dynamic_cast(b)) { + exclusion->push_back(vme->m_base.get()); } else { addition->push_back(b); } @@ -165,10 +148,26 @@ void RuleWithOperator::getVariablesExceptions(Transaction *t, } +void RuleWithOperator::getVariablesExceptions(Transaction &t, + variables::Variables *exclusion, variables::Variables *addition) { + getVariablesExceptionsHelper(exclusion, addition, + t.m_rules->m_exceptions.m_variable_update_target_by_tag, + [this, &t](const auto &tag) { return containsTag(*tag.get(), &t); }); + + getVariablesExceptionsHelper(exclusion, addition, + t.m_rules->m_exceptions.m_variable_update_target_by_msg, + [this, &t](const auto &msg) { return containsMsg(*msg.get(), &t); }); + + getVariablesExceptionsHelper(exclusion, addition, + t.m_rules->m_exceptions.m_variable_update_target_by_id, + [this](const auto &id) { return m_ruleId == id; }); +} + + inline void RuleWithOperator::getFinalVars(variables::Variables *vars, variables::Variables *exclusion, Transaction *trans) { variables::Variables addition; - getVariablesExceptions(trans, exclusion, &addition); + getVariablesExceptions(*trans, exclusion, &addition); // cppcheck-suppress ctunullpointer for (int i = 0; i < m_variables->size(); i++) { Variable *variable = m_variables->at(i); diff --git a/test/optimization/optimization.cc b/test/optimization/optimization.cc index f4014058..19298b0b 100644 --- a/test/optimization/optimization.cc +++ b/test/optimization/optimization.cc @@ -87,7 +87,7 @@ int main(int argc, char **argv) { continue; } - if (dynamic_cast(z.get()) != nullptr) { + if (dynamic_cast(z.get())) { std::string op = "Unconditional"; if (operators.count(op) > 0) { operators[op] = 1 + operators[op]; @@ -96,9 +96,7 @@ int main(int argc, char **argv) { } } - if (dynamic_cast(z.get()) != nullptr) { - auto *rwo = dynamic_cast(z.get()); - + if (auto rwo = dynamic_cast(z.get())) { std::string op = rwo->getOperatorName(); if (operators.count(op) > 0) { operators[op] = 1 + operators[op]; From e2b3c9594ff47a0d9abb71dfe234f73ecbf9816e Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Wed, 7 Aug 2024 08:33:03 -0700 Subject: [PATCH 29/75] Prevent concurrent access to data structure in resolve methods - As reported in #3054, the resolve methods in InMemoryPerProcess are not acquiring a lock/mutex to prevent concurrent access to the data structures that may be modified at the same time from other threads, and thus triggering undefined behaviour. - Replace inheritance of std::unordered_multimap data structure with data member to prevent potential clients to use it without acquiring the mutex to protect concurrent access. - Replace pthreads lock with std C++11 std::shared_mutex - Provides exclusive/shared lock access so that multiple readers can access the data at the same time, but only one writer. this is used to favor query performance by allowing more concurrent access to the data until an update needs to be performed. - Simplifies acquisition and disposal of lock/mutex with std::lock_guard, which has RAII semantics. - NOTE: Because std::shared_mutex is not recursive, calls to another function that tries to acquire the lock will fail. Introduced __store & __updateFirst helper methods to workaround this. - Updates to InMemoryPerProcess::resolveFirst - Updated the code to store the expired var in 'expiredVars' to delete them after iterating over the range (and releasing the read lock, as 'delIfExpired' needs to acquire it for exclusive access), as the current call to 'delIfExpired' would invalidate the range triggering undefined behaviour on the following iteration. - Noticed that in commit 118e1b3 the call to 'delIfExpired' in this function is done using 'it->second.getValue()'' instead of 'it->first', which seems incorrect (based on similar code in other resolveXXX functions). - Updated InMemoryPerProcess::delIfExpired to use 'std::find_if' (with a lambda that matches both the key and the 'isExpired' condition) because the data structure is a multimap. The version introduced in commit 118e1b3 could find an entry (not necessarily the first, because the map is unordered) where 'isExpired' is 'false' and exit, while another entry could be expired. --- .../backend/in_memory-per_process.cc | 246 +++++++++--------- .../backend/in_memory-per_process.h | 18 +- 2 files changed, 139 insertions(+), 125 deletions(-) diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index a4ca5e2e..57e87072 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -39,26 +39,48 @@ namespace backend { InMemoryPerProcess::InMemoryPerProcess(const std::string &name) : Collection(name) { - this->reserve(1000); - pthread_mutex_init(&m_lock, NULL); + m_map.reserve(1000); } InMemoryPerProcess::~InMemoryPerProcess() { - this->clear(); - pthread_mutex_destroy(&m_lock); + m_map.clear(); } -void InMemoryPerProcess::store(std::string key, std::string value) { - pthread_mutex_lock(&m_lock); - this->emplace(key, value); - pthread_mutex_unlock(&m_lock); + +template +inline void __store(Map &map, std::string key, std::string value) { + // NOTE: should be called with write-lock previously acquired + + map.emplace(key, value); +} + + +template +inline bool __updateFirst(Map &map, + const std::string &key, + const std::string &value) { + // NOTE: should be called with write-lock previously acquired + + if (auto search = map.find(key); search != map.end()) { + search->second.setValue(value); + return true; + } + + return false; +} + + +void InMemoryPerProcess::store(const std::string &key, const std::string &value) { + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + __store(m_map, key, value); } bool InMemoryPerProcess::storeOrUpdateFirst(const std::string &key, const std::string &value) { - if (updateFirst(key, value) == false) { - store(key, value); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + if (__updateFirst(m_map, key, value) == false) { + __store(m_map, key, value); } return true; } @@ -66,66 +88,59 @@ bool InMemoryPerProcess::storeOrUpdateFirst(const std::string &key, bool InMemoryPerProcess::updateFirst(const std::string &key, const std::string &value) { - pthread_mutex_lock(&m_lock); - - if (auto search = this->find(key); search != this->end()) { - search->second.setValue(value); - pthread_mutex_unlock(&m_lock); - return true; - } - - pthread_mutex_unlock(&m_lock); - return false; + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + return __updateFirst(m_map, key, value); } void InMemoryPerProcess::del(const std::string& key) { - pthread_mutex_lock(&m_lock); - this->erase(key); - pthread_mutex_unlock(&m_lock); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + m_map.erase(key); } void InMemoryPerProcess::delIfExpired(const std::string& key) { - pthread_mutex_lock(&m_lock); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) // Double check the status while within the mutex - auto iter = this->find(key); - if ((iter != this->end()) && (iter->second.isExpired())) { - this->erase(key); + const auto iter = std::find_if(m_map.begin(), m_map.end(), + [&key](const auto &x) { return x.first == key && x.second.isExpired(); }); + if (iter != m_map.end()) { + m_map.erase(key); } - pthread_mutex_unlock(&m_lock); } void InMemoryPerProcess::setExpiry(const std::string& key, int32_t expiry_seconds) { - pthread_mutex_lock(&m_lock); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) - if (auto search = this->find(key); search != this->end()) { + if (const auto search = m_map.find(key); search != m_map.end()) { search->second.setExpiry(expiry_seconds); - pthread_mutex_unlock(&m_lock); return; } // We allow an expiry value to be set for a key that has not (yet) had a value set. - auto iter = this->emplace(key, CollectionData()); + const auto iter = m_map.emplace(key, CollectionData()); iter->second.setExpiry(expiry_seconds); - - pthread_mutex_unlock(&m_lock); } void InMemoryPerProcess::resolveSingleMatch(const std::string& var, std::vector *l) { std::list expiredVars; - auto range = this->equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - if (it->second.isExpired()) { - expiredVars.push_back(it->first); - } else if (it->second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->push_back(new VariableValue(&m_name, &it->first, &it->second.getValue())); - } + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + const auto range = m_map.equal_range(var); + for (auto it = range.first; it != range.second; ++it) { + if (it->second.isExpired()) { + expiredVars.push_back(it->first); + } else if (it->second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->push_back(new VariableValue(&m_name, &it->first, &it->second.getValue())); + } + } } + for (const auto& expiredVar : expiredVars) { delIfExpired(expiredVar); } @@ -134,40 +149,45 @@ void InMemoryPerProcess::resolveSingleMatch(const std::string& var, void InMemoryPerProcess::resolveMultiMatches(const std::string& var, std::vector *l, variables::KeyExclusions &ke) { - size_t keySize = var.size(); + const auto keySize = var.size(); l->reserve(15); std::list expiredVars; - if (keySize == 0) { - for (auto &i : *this) { - if (ke.toOmit(i.first)) { - continue; + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + if (keySize == 0) { + for (auto &i : m_map) { + if (ke.toOmit(i.first)) { + continue; + } + if (i.second.isExpired()) { + expiredVars.push_back(i.first); + } else if (i.second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->insert(l->begin(), new VariableValue(&m_name, &i.first, + &i.second.getValue())); + } } - if (i.second.isExpired()) { - expiredVars.push_back(i.first); - } else if (i.second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->insert(l->begin(), new VariableValue(&m_name, &i.first, - &i.second.getValue())); - } - } - } else { - auto range = this->equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - if (ke.toOmit(var)) { - continue; + } else { + const auto range = m_map.equal_range(var); + for (auto it = range.first; it != range.second; ++it) { + if (ke.toOmit(var)) { + continue; + } + if (it->second.isExpired()) { + expiredVars.push_back(it->first); + } else if (it->second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->insert(l->begin(), new VariableValue(&m_name, &var, + &it->second.getValue())); + } } - if (it->second.isExpired()) { - expiredVars.push_back(it->first); - } else if (it->second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->insert(l->begin(), new VariableValue(&m_name, &var, - &it->second.getValue())); - } } } + for (const auto& expiredVar : expiredVars) { delIfExpired(expiredVar); } @@ -176,47 +196,30 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var, void InMemoryPerProcess::resolveRegularExpression(const std::string& var, std::vector *l, variables::KeyExclusions &ke) { - - //if (var.find(":") == std::string::npos) { - // return; - //} - //if (var.size() < var.find(":") + 3) { - // return; - //} - //std::string col = std::string(var, 0, var.find(":")); - //std::string name = std::string(var, var.find(":") + 2, - // var.size() - var.find(":") - 3); - //size_t keySize = col.size(); Utils::Regex r(var, true); std::list expiredVars; - for (const auto& x : *this) { - //if (x.first.size() <= keySize + 1) { - // continue; - //} - //if (x.first.at(keySize) != ':') { - // continue; - //} - //if (std::string(x.first, 0, keySize) != col) { - // continue; - //} - //std::string content = std::string(x.first, keySize + 1, - // x.first.size() - keySize - 1); - int ret = Utils::regex_search(x.first, r); - if (ret <= 0) { - continue; + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + for (const auto& x : m_map) { + const auto ret = Utils::regex_search(x.first, r); + if (ret <= 0) { + continue; + } + if (ke.toOmit(x.first)) { + continue; + } + if (x.second.isExpired()) { + expiredVars.push_back(x.first); + } else if (x.second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->insert(l->begin(), new VariableValue(&m_name, &x.first, &x.second.getValue())); + } } - if (ke.toOmit(x.first)) { - continue; - } - if (x.second.isExpired()) { - expiredVars.push_back(x.first); - } else if (x.second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->insert(l->begin(), new VariableValue(&m_name, &x.first, &x.second.getValue())); - } } + for (const auto& expiredVar : expiredVars) { delIfExpired(expiredVar); } @@ -225,18 +228,29 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var, std::unique_ptr InMemoryPerProcess::resolveFirst( const std::string& var) { - auto range = equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - if (it->second.isExpired()) { - delIfExpired(it->second.getValue()); - } else if (it->second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - return std::unique_ptr(new std::string(it->second.getValue())); - } + std::unique_ptr ret; + std::list expiredVars; + + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + const auto range = m_map.equal_range(var); + for (auto it = range.first; it != range.second; ++it) { + if (it->second.isExpired()) { + expiredVars.push_back(it->first); + } else if (it->second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + ret = std::make_unique(it->second.getValue()); + } + } } - return NULL; + for (const auto& expiredVar : expiredVars) { + delIfExpired(expiredVar); + } + + return ret; } diff --git a/src/collection/backend/in_memory-per_process.h b/src/collection/backend/in_memory-per_process.h index 3cacdca0..2e283d25 100644 --- a/src/collection/backend/in_memory-per_process.h +++ b/src/collection/backend/in_memory-per_process.h @@ -12,7 +12,6 @@ * directly using the email address security@modsecurity.org. * */ -#include #ifdef __cplusplus @@ -24,6 +23,7 @@ #include #include #include +#include #endif @@ -71,13 +71,11 @@ struct MyHash{ }; class InMemoryPerProcess : - public std::unordered_multimap*/MyHash, MyEqual>, public Collection { public: explicit InMemoryPerProcess(const std::string &name); ~InMemoryPerProcess(); - void store(std::string key, std::string value); + void store(const std::string &key, const std::string &value); bool storeOrUpdateFirst(const std::string &key, const std::string &value) override; @@ -103,21 +101,23 @@ class InMemoryPerProcess : variables::KeyExclusions &ke) override; /* store */ - virtual void store(std::string key, std::string compartment, + virtual void store(const std::string &key, std::string &compartment, std::string value) { - std::string nkey = compartment + "::" + key; + const auto nkey = compartment + "::" + key; store(nkey, value); } - virtual void store(std::string key, std::string compartment, + virtual void store(const std::string &key, const std::string &compartment, std::string compartment2, std::string value) { - std::string nkey = compartment + "::" + compartment2 + "::" + key; + const auto nkey = compartment + "::" + compartment2 + "::" + key; store(nkey, value); } private: - pthread_mutex_t m_lock; + std::unordered_multimap*/MyHash, MyEqual> m_map; + std::shared_mutex m_mutex; }; } // namespace backend From 4e15f9ef7118088d3c414dabe4fb1d3cc62b4e13 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Wed, 7 Aug 2024 11:50:55 -0700 Subject: [PATCH 30/75] Turn off LMDB by default in Windows build to align with defaults for other platforms - Replaced WITHOUT_XXX build options with WITH_XXX to make it easier to understand and configure. - Updated GitHub workflow to align with these changes and include a build 'with lmdb' (again, analogous to non-Windows configurations) --- .github/workflows/ci.yml | 10 +++++----- build/win32/CMakeLists.txt | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10ac5144..71ca3c7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,11 +132,11 @@ jobs: configuration: [Release] configure: - {label: "full", opt: "" } - - {label: "wo curl", opt: "-DWITHOUT_CURL=ON" } - - {label: "wo lmdb", opt: "-DWITHOUT_LMDB=ON" } - - {label: "wo lua", opt: "-DWITHOUT_LUA=ON" } - - {label: "wo maxmind", opt: "-DWITHOUT_MAXMIND=ON" } - - {label: "wo libxml", opt: "-WITHOUT_LIBXML2=ON" } + - {label: "wo curl", opt: "-DWITH_CURL=OFF" } + - {label: "wo lua", opt: "-DWITH_LUA=OFF" } + - {label: "wo maxmind", opt: "-DWITH_MAXMIND=OFF" } + - {label: "wo libxml", opt: "-DWITH_LIBXML2=OFF" } + - {label: "with lmdb", opt: "-DWITH_LMDB=ON" } steps: - uses: actions/checkout@v4 with: diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index bdb9a45f..83b020a7 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -2,13 +2,13 @@ cmake_minimum_required(VERSION 3.24) set(BASE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -option(WITHOUT_LMDB "Include LMDB support" OFF) -option(WITHOUT_LUA "Include LUA support" OFF) -option(WITHOUT_LIBXML2 "Include LibXML2 support" OFF) -option(WITHOUT_MAXMIND "Include MaxMind support" OFF) -option(WITHOUT_CURL "Include CURL support" OFF) +option(WITH_LMDB "Include LMDB support" OFF) +option(WITH_LUA "Include LUA support" ON) +option(WITH_LIBXML2 "Include LibXML2 support" ON) +option(WITH_MAXMIND "Include MaxMind support" ON) +option(WITH_CURL "Include CURL support" ON) -option(USE_ASAN "Build with Address Sanitizer" OFF) +option(USE_ASAN "Build with Address Sanitizer" OFF) # common compiler settings @@ -93,17 +93,17 @@ set(HAVE_SSDEEP 0) # should always be zero, no conan package available macro(enable_feature flag option) if(${option}) - set(${flag} 0) + set(${flag} 1) # ON else() - set(${flag} 1) + set(${flag} 0) # OFF endif() endmacro() -enable_feature(HAVE_LMDB ${WITHOUT_LMDB}) -enable_feature(HAVE_LUA ${WITHOUT_LUA}) -enable_feature(HAVE_LIBXML2 ${WITHOUT_LIBXML2}) -enable_feature(HAVE_MAXMIND ${WITHOUT_MAXMIND}) -enable_feature(HAVE_CURL ${WITHOUT_CURL}) +enable_feature(HAVE_LMDB ${WITH_LMDB}) +enable_feature(HAVE_LUA ${WITH_LUA}) +enable_feature(HAVE_LIBXML2 ${WITH_LIBXML2}) +enable_feature(HAVE_MAXMIND ${WITH_MAXMIND}) +enable_feature(HAVE_CURL ${WITH_CURL}) include(${CMAKE_CURRENT_LIST_DIR}/ConfigureChecks.cmake) From 293cd214c79c8104c87d52188987956ca3ce1b36 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Wed, 7 Aug 2024 13:54:58 -0700 Subject: [PATCH 31/75] Removed usage of pthreads and replaced with std C++ features - Replaced pthread_mutex_t in modsecurity::operators::Pm with std::mutex - Replaced pthread's thread usage in reading_logs_via_rule_message example with std::thread. - Simplified and modernized C++ code. - Removed unnecessary includes of pthread.h --- build/win32/CMakeLists.txt | 4 +- build/win32/conanfile.txt | 1 - examples/multiprocess_c/Makefile.am | 1 - .../reading_logs_via_rule_message/Makefile.am | 1 - .../reading_logs_via_rule_message.h | 67 ++++++------------- examples/reading_logs_with_offset/Makefile.am | 1 - examples/using_bodies_in_chunks/Makefile.am | 2 - .../backend/in_memory-per_process.cc | 2 - src/collection/backend/lmdb.cc | 2 - src/collection/backend/lmdb.h | 2 - src/operators/pm.cc | 11 +-- src/operators/pm.h | 3 +- 12 files changed, 27 insertions(+), 70 deletions(-) diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index 83b020a7..1e6303fd 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -110,7 +110,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/ConfigureChecks.cmake) configure_file(config.h.cmake ${BASE_DIR}/src/config.h) find_package(PCRE2 REQUIRED) -find_package(PThreads4W REQUIRED) find_package(Poco REQUIRED) find_package(dirent REQUIRED) # used only by tests (check dirent::dirent refernces) @@ -139,7 +138,7 @@ add_library(libModSecurity SHARED ${libModSecuritySources}) target_compile_definitions(libModSecurity PRIVATE WITH_PCRE2) target_include_directories(libModSecurity PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others ${MBEDTLS_DIR}/include) -target_link_libraries(libModSecurity PRIVATE pcre2::pcre2 pthreads4w::pthreads4w libinjection mbedcrypto Poco::Poco Iphlpapi.lib) +target_link_libraries(libModSecurity PRIVATE pcre2::pcre2 libinjection mbedcrypto Poco::Poco Iphlpapi.lib) macro(add_package_dependency project compile_definition link_library flag) if(${flag}) @@ -255,7 +254,6 @@ setExampleTargetProperties(using_bodies_in_chunks) # reading_logs_via_rule_message add_executable(reading_logs_via_rule_message ${BASE_DIR}/examples/reading_logs_via_rule_message/simple_request.cc) setExampleTargetProperties(reading_logs_via_rule_message) -target_link_libraries(reading_logs_via_rule_message PRIVATE libModSecurity pthreads4w::pthreads4w) # reading_logs_with_offset add_executable(reading_logs_with_offset ${BASE_DIR}/examples/reading_logs_with_offset/read.cc) diff --git a/build/win32/conanfile.txt b/build/win32/conanfile.txt index b1a69821..b8f9721d 100644 --- a/build/win32/conanfile.txt +++ b/build/win32/conanfile.txt @@ -1,7 +1,6 @@ [requires] yajl/2.1.0 pcre2/10.42 -pthreads4w/3.0.0 libxml2/2.12.6 lua/5.4.6 libcurl/8.6.0 diff --git a/examples/multiprocess_c/Makefile.am b/examples/multiprocess_c/Makefile.am index 85c26487..726d1d90 100644 --- a/examples/multiprocess_c/Makefile.am +++ b/examples/multiprocess_c/Makefile.am @@ -15,7 +15,6 @@ multi_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(LUA_LDFLAGS) \ diff --git a/examples/reading_logs_via_rule_message/Makefile.am b/examples/reading_logs_via_rule_message/Makefile.am index 210edef3..55d3a93f 100644 --- a/examples/reading_logs_via_rule_message/Makefile.am +++ b/examples/reading_logs_via_rule_message/Makefile.am @@ -21,7 +21,6 @@ simple_request_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(LMDB_LDFLAGS) \ diff --git a/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h b/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h index 6b280048..33148cd7 100644 --- a/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h +++ b/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h @@ -13,14 +13,19 @@ * */ +#ifndef EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ +#define EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ + #include #include #include +#include #include -#include + +#include "modsecurity/rule_message.h" -#define NUM_THREADS 100 +constexpr auto NUM_THREADS = 100; char request_header[] = "" \ @@ -62,40 +67,21 @@ char response_body[] = "" \ char ip[] = "200.249.12.31"; -#include "modsecurity/rule_message.h" -#ifndef EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ -#define EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ +static void process_request(modsecurity::ModSecurity *modsec, modsecurity::RulesSet *rules) { + for (auto z = 0; z < 10000; z++) { + auto modsecTransaction = std::make_unique(modsec, rules, nullptr); - -struct data_ms { - modsecurity::ModSecurity *modsec; - modsecurity::RulesSet *rules; -}; - -#if defined _MSC_VER -#pragma warning(push) -#pragma warning(disable:4716) // avoid error C4716: 'process_request': must return a value, as MSVC C++ compiler doesn't support [[noreturn]] -#pragma warning(disable:4715) // avoid warning c4715: 'process_request' : not all control paths return a value -#endif - -[[noreturn]] static void *process_request(void *data) { - struct data_ms *a = (struct data_ms *)data; - modsecurity::ModSecurity *modsec = a->modsec; - modsecurity::RulesSet *rules = a->rules; - int z = 0; - - for (z = 0; z < 10000; z++) { - modsecurity::Transaction *modsecTransaction = \ - new modsecurity::Transaction(modsec, rules, NULL); modsecTransaction->processConnection(ip, 12345, "127.0.0.1", 80); modsecTransaction->processURI(request_uri, "GET", "1.1"); std::this_thread::sleep_for(std::chrono::microseconds(10)); + modsecTransaction->addRequestHeader("Host", "net.tutsplus.com"); modsecTransaction->processRequestHeaders(); modsecTransaction->processRequestBody(); + modsecTransaction->addResponseHeader("HTTP/1.1", "200 OK"); modsecTransaction->processResponseHeaders(200, "HTTP 1.2"); @@ -103,18 +89,11 @@ struct data_ms { (const unsigned char*)response_body, strlen((const char*)response_body)); modsecTransaction->processResponseBody(); + modsecTransaction->processLogging(); - - delete modsecTransaction; } - - pthread_exit(nullptr); } -#if defined _MSC_VER -#pragma warning(pop) -#endif - class ReadingLogsViaRuleMessage { public: ReadingLogsViaRuleMessage(char *request_header, @@ -134,11 +113,6 @@ class ReadingLogsViaRuleMessage { { } int process() const { - pthread_t threads[NUM_THREADS]; - int i; - struct data_ms dms; - void *status; - auto modsec = std::make_unique(); modsec->setConnectorInformation("ModSecurity-test v0.0.1-alpha" \ " (ModSecurity test)"); @@ -152,18 +126,19 @@ class ReadingLogsViaRuleMessage { return -1; } - dms.modsec = modsec.get(); - dms.rules = rules.get(); + std::array threads; - for (i = 0; i < NUM_THREADS; i++) { - pthread_create(&threads[i], NULL, process_request, - reinterpret_cast(&dms)); + for (auto i = 0; i != threads.size(); ++i) { + threads[i] = std::thread( + [&modsec, &rules]() { + process_request(modsec.get(), rules.get()); + }); } std::this_thread::sleep_for(std::chrono::microseconds(10000)); - for (i=0; i < NUM_THREADS; i++) { - pthread_join(threads[i], &status); + for (auto i = 0; i != threads.size(); ++i) { + threads[i].join(); std::cout << "Main: completed thread id :" << i << std::endl; } diff --git a/examples/reading_logs_with_offset/Makefile.am b/examples/reading_logs_with_offset/Makefile.am index f845c583..3ecda10c 100644 --- a/examples/reading_logs_with_offset/Makefile.am +++ b/examples/reading_logs_with_offset/Makefile.am @@ -21,7 +21,6 @@ read_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(LMDB_LDFLAGS) \ diff --git a/examples/using_bodies_in_chunks/Makefile.am b/examples/using_bodies_in_chunks/Makefile.am index aa28fe07..5d645379 100644 --- a/examples/using_bodies_in_chunks/Makefile.am +++ b/examples/using_bodies_in_chunks/Makefile.am @@ -21,12 +21,10 @@ simple_request_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(MAXMIND_LDFLAGS) \ $(LMDB_LDFLAGS) \ - -lpthread \ $(LUA_LDFLAGS) \ $(SSDEEP_LDFLAGS) \ $(YAJL_LDFLAGS) diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index 57e87072..b16ee843 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -25,8 +25,6 @@ #include #endif -#include - #include "modsecurity/variable_value.h" #include "src/utils/regex.h" #include "src/utils/string.h" diff --git a/src/collection/backend/lmdb.cc b/src/collection/backend/lmdb.cc index 85c68e3c..4a77f5fb 100644 --- a/src/collection/backend/lmdb.cc +++ b/src/collection/backend/lmdb.cc @@ -27,8 +27,6 @@ #include #include -#include - #include "modsecurity/variable_value.h" #include "src/utils/regex.h" #include "src/variables/variable.h" diff --git a/src/collection/backend/lmdb.h b/src/collection/backend/lmdb.h index 15c4fa9f..49633e37 100644 --- a/src/collection/backend/lmdb.h +++ b/src/collection/backend/lmdb.h @@ -27,12 +27,10 @@ #ifdef WITH_LMDB #include -#include #endif // WITH_LMDB #include #include #include -#include #include "modsecurity/variable_value.h" #include "modsecurity/collection/collection.h" diff --git a/src/operators/pm.cc b/src/operators/pm.cc index ebf31c40..d92fc163 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -39,9 +39,6 @@ Pm::~Pm() { free(m_p); m_p = NULL; -#ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_destroy(&m_lock); -#endif } @@ -89,11 +86,12 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, pt.ptr = NULL; const char *match = NULL; #ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_lock(&m_lock); + { + const std::lock_guard lock(m_mutex); #endif rc = acmp_process_quick(&pt, &match, input.c_str(), input.length()); #ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_unlock(&m_lock); + } #endif if (rc >= 0 && transaction) { @@ -118,9 +116,6 @@ bool Pm::init(const std::string &file, std::string *error) { std::istringstream *iss; const char *err = NULL; -#ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_init(&m_lock, NULL); -#endif char *content = parse_pm_content(m_param.c_str(), m_param.length(), &err); if (content == NULL) { iss = new std::istringstream(m_param); diff --git a/src/operators/pm.h b/src/operators/pm.h index b090ec5d..ed5649af 100644 --- a/src/operators/pm.h +++ b/src/operators/pm.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "src/operators/operator.h" #include "src/utils/acmp.h" @@ -56,7 +57,7 @@ class Pm : public Operator { #ifdef MODSEC_MUTEX_ON_PM private: - pthread_mutex_t m_lock; + std::mutex m_mutex; #endif }; From 4bf9616f9e88ea758f0c334e697261702bc07d39 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 9 Aug 2024 10:56:36 -0700 Subject: [PATCH 32/75] Adding multithreaded example from issue #3054 (by airween) - Rewritten to use C++ libModSecurity API and std::thread (instead of pthreads) --- .gitignore | 1 + build/win32/CMakeLists.txt | 4 ++ build/win32/README.md | 1 + configure.ac | 1 + examples/Makefile.am | 1 + examples/multithread/Makefile.am | 54 +++++++++++++++++++++ examples/multithread/basic_rules.conf | 14 ++++++ examples/multithread/multithread.cc | 68 +++++++++++++++++++++++++++ 8 files changed, 144 insertions(+) create mode 100644 examples/multithread/Makefile.am create mode 100644 examples/multithread/basic_rules.conf create mode 100644 examples/multithread/multithread.cc diff --git a/.gitignore b/.gitignore index be0de155..9515fb56 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ ltmain.sh examples/simple_example_using_c/test /tools/rules-check/modsec-rules-check examples/multiprocess_c/multi +examples/multithread/multithread examples/reading_logs_via_rule_message/simple_request examples/reading_logs_with_offset/read examples/using_bodies_in_chunks/simple_request diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index 1e6303fd..cebf4c9b 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -259,6 +259,10 @@ setExampleTargetProperties(reading_logs_via_rule_message) add_executable(reading_logs_with_offset ${BASE_DIR}/examples/reading_logs_with_offset/read.cc) setExampleTargetProperties(reading_logs_with_offset) +# multithread +add_executable(multithread ${BASE_DIR}/examples/multithread/multithread.cc) +setExampleTargetProperties(multithread) + # tools # diff --git a/build/win32/README.md b/build/win32/README.md index 7b70cfbd..85fd868e 100644 --- a/build/win32/README.md +++ b/build/win32/README.md @@ -51,6 +51,7 @@ Built files will be located in the directory: `build\win32\build\[build_configur * `using_bodies_in_chunks.exe` * `reading_logs_via_rule_message.exe` * `reading_logs_with_offset.exe` + * `multithread.exe` * Executable files for tools * `rules_check.exe` diff --git a/configure.ac b/configure.ac index 3a0fbb48..34281a3f 100644 --- a/configure.ac +++ b/configure.ac @@ -423,6 +423,7 @@ AM_COND_IF([EXAMPLES], examples/Makefile \ examples/simple_example_using_c/Makefile \ examples/multiprocess_c/Makefile \ + examples/multithread/Makefile \ examples/reading_logs_with_offset/Makefile \ examples/reading_logs_via_rule_message/Makefile \ examples/using_bodies_in_chunks/Makefile \ diff --git a/examples/Makefile.am b/examples/Makefile.am index 609cb93e..2dbb21ac 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -4,6 +4,7 @@ ACLOCAL_AMFLAGS = -I build SUBDIRS = \ multiprocess_c \ + multithread \ reading_logs_with_offset \ reading_logs_via_rule_message \ simple_example_using_c \ diff --git a/examples/multithread/Makefile.am b/examples/multithread/Makefile.am new file mode 100644 index 00000000..40e81dd1 --- /dev/null +++ b/examples/multithread/Makefile.am @@ -0,0 +1,54 @@ + + +noinst_PROGRAMS = multithread + +multithread_SOURCES = \ + multithread.cc + +multithread_LDADD = \ + $(CURL_LDADD) \ + $(GEOIP_LDADD) \ + $(GLOBAL_LDADD) \ + $(LIBXML2_LDADD) \ + $(LMDB_LDADD) \ + $(MAXMIND_LDADD) \ + $(LUA_LDADD) \ + $(PCRE_LDADD) \ + $(SSDEEP_LDADD) \ + $(YAJL_LDADD) + +multithread_LDFLAGS = \ + -L$(top_builddir)/src/.libs/ \ + $(GEOIP_LDFLAGS) \ + -lmodsecurity \ + -lm \ + -lstdc++ \ + $(LMDB_LDFLAGS) \ + $(LUA_LDFLAGS) \ + $(MAXMIND_LDFLAGS) \ + $(SSDEEP_LDFLAGS) \ + $(YAJL_LDFLAGS) + +multithread_CPPFLAGS = \ + $(GLOBAL_CFLAGS) \ + -I$(top_builddir)/headers \ + -I$(top_builddir) \ + -g \ + -I../others \ + -fPIC \ + -O3 \ + $(CURL_CFLAGS) \ + $(GEOIP_CFLAGS) \ + $(GLOBAL_CPPFLAGS) \ + $(MODSEC_NO_LOGS) \ + $(YAJL_CFLAGS) \ + $(LMDB_CFLAGS) \ + $(LUA_CFLAGS) \ + $(PCRE_CFLAGS) \ + $(LIBXML2_CFLAGS) + + +MAINTAINERCLEANFILES = \ + Makefile.in + + diff --git a/examples/multithread/basic_rules.conf b/examples/multithread/basic_rules.conf new file mode 100644 index 00000000..cff18342 --- /dev/null +++ b/examples/multithread/basic_rules.conf @@ -0,0 +1,14 @@ +SecDebugLog debug.log +SecDebugLogLevel 9 + + +SecRule REQUEST_HEADERS:User-Agent ".*" "id:1,phase:1,t:sha1,t:hexEncode,setvar:tx.ua_hash=%{MATCHED_VAR}" + +SecAction "id:2,phase:2,initcol:ip=%{REMOTE_ADDR}_%{tx.ua_hash}" + +SecRule REQUEST_HEADERS:User-Agent "@rx .*" "id:3,phase:2,setvar:ip.auth_attempt=+1" + +SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar,expirevar:ip.foo=2" +#SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar" +SecRule IP "@rx bar" "id:5,phase:2,pass" +SecRule IP:auth_attempt "@rx bar" "id:6,phase:2,pass" diff --git a/examples/multithread/multithread.cc b/examples/multithread/multithread.cc new file mode 100644 index 00000000..4233bc71 --- /dev/null +++ b/examples/multithread/multithread.cc @@ -0,0 +1,68 @@ +#include +#include +#include + +#include +#include +#include + +static void process_request(modsecurity::ModSecurity *modsec, modsecurity::RulesSet *rules, int tid) { + std::cout << "Hello World! It's me, thread #" << tid << std::endl; + + for(int i = 0; i != 1'000; i++) { + auto modsecTransaction = std::make_unique(modsec, rules, nullptr); + + modsecTransaction->processConnection("127.0.0.1", 12345, "127.0.0.1", 80); + modsecTransaction->processURI( + "https://www.modsecurity.org/test?foo=herewego", + "GET", "1.1"); + + modsecTransaction->addRequestHeader("User-Agent", + "Basic ModSecurity example"); + modsecTransaction->processRequestHeaders(); + modsecTransaction->processRequestBody(); + + modsecTransaction->addResponseHeader("HTTP/1.1", + "200 OK"); + modsecTransaction->processResponseHeaders(200, "HTTP 1.2"); + modsecTransaction->processResponseBody(); + + modsecTransaction->processLogging(); + + std::this_thread::sleep_for(std::chrono::microseconds(100)); + } + + std::cout << "Thread #" << tid << " exits" << std::endl; +} + +int main (int argc, char *argv[]) { + auto modsec = std::make_unique(); + modsec->setConnectorInformation("ModSecurity-test v0.0.1-alpha (Simple " \ + "example on how to use ModSecurity API"); + + char main_rule_uri[] = "basic_rules.conf"; + auto rules = std::make_unique(); + if (rules->loadFromUri(main_rule_uri) < 0) { + std::cerr << "Problems loading the rules..." << std::endl; + std::cerr << rules->m_parserError.str() << std::endl; + return -1; + } + + constexpr auto NUM_THREADS = 100; + std::array threads; + + for (auto i = 0; i != threads.size(); ++i) { + threads[i] = std::thread( + [&modsec, &rules, i]() { + process_request(modsec.get(), rules.get(), i); + }); + } + + std::this_thread::sleep_for(std::chrono::microseconds(10000)); + + for (auto i = 0; i != threads.size(); ++i) { + threads[i].join(); + } + + return 0; +} \ No newline at end of file From bb07de9ad7e574edc24496c184730ca15fffe94e Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Sun, 28 Apr 2024 21:45:34 -0300 Subject: [PATCH 33/75] toupper/tolower is already receiving a copy, so it doesn't need to create a new one to transform it - Make functions inline to improve performance - Introduced helper method toCaseHelper to remove code duplication --- src/utils/string.cc | 29 ----------------------------- src/utils/string.h | 27 ++++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/utils/string.cc b/src/utils/string.cc index 276fd31f..195d5a1b 100644 --- a/src/utils/string.cc +++ b/src/utils/string.cc @@ -20,12 +20,9 @@ #include #include -#include #include #include -#include #include -#include #include #include @@ -148,32 +145,6 @@ std::string toHexIfNeeded(const std::string &str, bool escape_spec) { } -std::string tolower(std::string str) { - std::string value; - value.resize(str.length()); - - std::transform(str.begin(), - str.end(), - value.begin(), - ::tolower); - - return value; -} - - -std::string toupper(std::string str) { - std::string value; - value.resize(str.length()); - - std::transform(str.begin(), - str.end(), - value.begin(), - ::toupper); - - return value; -} - - std::vector ssplit(std::string str, char delimiter) { std::vector internal; std::stringstream ss(str); // Turn the string into a stream. diff --git a/src/utils/string.h b/src/utils/string.h index 1cd63296..54136e49 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -14,9 +14,10 @@ */ #include -#include #include #include +#include +#include #ifndef SRC_UTILS_STRING_H_ #define SRC_UTILS_STRING_H_ @@ -62,8 +63,6 @@ std::string limitTo(int amount, const std::string &str); std::string removeBracketsIfNeeded(std::string a); std::string string_to_hex(const std::string& input); std::string toHexIfNeeded(const std::string &str, bool escape_spec = false); -std::string tolower(std::string str); -std::string toupper(std::string str); std::vector ssplit(std::string str, char delimiter); std::pair ssplit_pair(const std::string& str, char delimiter); std::vector split(std::string str, char delimiter); @@ -77,6 +76,28 @@ unsigned char x2c(const unsigned char *what); unsigned char xsingle2c(const unsigned char *what); unsigned char *c2x(unsigned what, unsigned char *where); + +template +inline std::string toCaseHelper(std::string str, Operation op) { + std::transform(str.begin(), + str.end(), + str.begin(), + op); + + return str; +} + + +inline std::string tolower(std::string str) { // cppcheck-suppress passedByValue ; copied value is used for in-place transformation + return toCaseHelper(str, ::tolower); +} + + +inline std::string toupper(std::string str) { // cppcheck-suppress passedByValue ; copied value is used for in-place transformation + return toCaseHelper(str, ::toupper); +} + + } // namespace string } // namespace utils } // namespace modsecurity From f8dd09f7c9b740dadb6e10468263dab9162e8974 Mon Sep 17 00:00:00 2001 From: eduar-hte <130087371+eduar-hte@users.noreply.github.com> Date: Sat, 18 May 2024 16:55:41 +0000 Subject: [PATCH 34/75] Avoid creating a new std::string on the heap to create VariableValue - Introduced helper method addVariableOrigin to reduce code duplication. --- src/variables/rule.h | 65 +++++++++++++++------------------------- src/variables/variable.h | 5 ++-- src/variables/xml.cc | 5 ++-- 3 files changed, 28 insertions(+), 47 deletions(-) diff --git a/src/variables/rule.h b/src/variables/rule.h index 3d3cbcc0..eed98c8a 100644 --- a/src/variables/rule.h +++ b/src/variables/rule.h @@ -35,7 +35,7 @@ namespace variables { class Rule_DictElement : public VariableDictElement { \ public: explicit Rule_DictElement(const std::string &dictElement) - : VariableDictElement(std::string("RULE"), dictElement) { } + : VariableDictElement(m_rule, dictElement) { } static void id(Transaction *t, RuleWithActions *rule, @@ -49,13 +49,8 @@ class Rule_DictElement : public VariableDictElement { \ if (!r || r->m_ruleId == 0) { return; } - std::string *a = new std::string(std::to_string(r->m_ruleId)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_id, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + + addVariableOrigin(m_rule_id, std::to_string(r->m_ruleId), l); } @@ -72,13 +67,7 @@ class Rule_DictElement : public VariableDictElement { \ return; } - std::string *a = new std::string(r->m_rev); - VariableValue *var = new VariableValue(&m_rule, &m_rule_rev, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_rev, r->m_rev, l); } @@ -92,13 +81,7 @@ class Rule_DictElement : public VariableDictElement { \ } if (r && r->hasSeverity()) { - std::string *a = new std::string(std::to_string(r->severity())); - VariableValue *var = new VariableValue(&m_rule, &m_rule_severity, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_severity, std::to_string(r->severity()), l); } } @@ -113,13 +96,7 @@ class Rule_DictElement : public VariableDictElement { \ } if (r && r->hasLogData()) { - std::string *a = new std::string(r->logData(t)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_logdata, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_logdata, r->logData(t), l); } } @@ -133,36 +110,30 @@ class Rule_DictElement : public VariableDictElement { \ } if (r && r->hasMsg()) { - std::string *a = new std::string(r->msg(t)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_msg, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_msg, r->msg(t), l); } } void evaluate(Transaction *t, RuleWithActions *rule, std::vector *l) override { - if (m_dictElement == "id") { + if (m_dictElement == m_rule_id) { id(t, rule, l); return; } - if (rule && m_dictElement == "rev") { + if (rule && m_dictElement == m_rule_rev) { rev(t, rule, l); return; } - if (rule && m_dictElement == "severity") { + if (rule && m_dictElement == m_rule_severity) { severity(t, rule, l); return; } - if (m_dictElement == "logdata") { + if (m_dictElement == m_rule_logdata) { logData(t, rule, l); return; } - if (m_dictElement == "msg") { + if (m_dictElement == m_rule_msg) { msg(t, rule, l); return; } @@ -174,6 +145,18 @@ class Rule_DictElement : public VariableDictElement { \ static const std::string m_rule_severity; static const std::string m_rule_logdata; static const std::string m_rule_msg; + +private: + + static inline void addVariableOrigin(const std::string &key, + const std::string &value, + std::vector *l) { + auto var = new VariableValue(&m_rule, &key, + &value + ); + var->addOrigin(); + l->push_back(var); + } }; diff --git a/src/variables/variable.h b/src/variables/variable.h index e854aca7..fc4671bb 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -707,9 +707,8 @@ class VariableModificatorCount : public Variable { } reslIn.clear(); - std::string *res = new std::string(std::to_string(count)); - val = new VariableValue(m_fullName.get(), res); - delete res; + auto res = std::to_string(count); + val = new VariableValue(m_fullName.get(), &res); l->push_back(val); return; diff --git a/src/variables/xml.cc b/src/variables/xml.cc index 9b3d8ff9..03dbc967 100644 --- a/src/variables/xml.cc +++ b/src/variables/xml.cc @@ -124,13 +124,12 @@ void XML::evaluate(Transaction *t, content = reinterpret_cast( xmlNodeGetContent(nodes->nodeTab[i])); if (content != NULL) { - std::string *a = new std::string(content); + auto a = std::string(content); VariableValue *var = new VariableValue(m_fullName.get(), - a); + &a); if (!m_keyExclusion.toOmit(*m_fullName)) { l->push_back(var); } - delete a; xmlFree(content); } } From 1534ee24488b00decc7611f38fbbc95f7b9634ab Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Thu, 30 May 2024 16:32:16 +0000 Subject: [PATCH 35/75] Removed unnecessary copies --- src/request_body_processor/multipart.cc | 31 +++++++------------------ 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index d9ed6c6d..93df5e7f 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -70,22 +70,20 @@ void MultipartPartTmpFile::Open() { localtime_r(&tt, &timeinfo); - char tstr[300] {}; - strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo); + char tstr[17]; + strftime(tstr, std::size(tstr), "/%Y%m%d-%H%M%S", &timeinfo); std::string path = m_transaction->m_rules->m_uploadDirectory.m_value; path = path + tstr + "-" + *m_transaction->m_id.get(); path += "-file-XXXXXX"; - char* tmp = strdup(path.c_str()); #ifndef WIN32 - m_tmp_file_fd = mkstemp(tmp); + m_tmp_file_fd = mkstemp(path.data()); #else - _mktemp_s(tmp, path.length()+1); - m_tmp_file_fd = _open(tmp, _O_CREAT | _O_EXCL | _O_RDWR); + _mktemp_s(path.data(), path.length()+1); + m_tmp_file_fd = _open(path.c_str(), _O_CREAT | _O_EXCL | _O_RDWR); #endif - m_tmp_file_name.assign(tmp); - free(tmp); + m_tmp_file_name = path; ms_dbg_a(m_transaction, 4, "MultipartPartTmpFile: Create filename= " + m_tmp_file_name); int mode = m_transaction->m_rules->m_uploadFileMode.m_value; @@ -1271,22 +1269,10 @@ int Multipart::multipart_complete(std::string *error) { int Multipart::count_boundary_params(const std::string& str_header_value) { - std::string lower = utils::string::tolower(str_header_value); - const char *header_value = lower.c_str(); - char *duplicate = NULL; - char *s = NULL; int count = 0; - if (header_value == NULL) { - return -1; - } - - duplicate = strdup(header_value); - if (duplicate == NULL) { - return -1; - } - - s = duplicate; + const auto lower = utils::string::tolower(str_header_value); + const char *s = lower.c_str(); while ((s = strstr(s, "boundary")) != NULL) { s += 8; @@ -1295,7 +1281,6 @@ int Multipart::count_boundary_params(const std::string& str_header_value) { } } - free(duplicate); return count; } From 8b17f3691fc618614daa8ff043f39d2ed3bed17c Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 24 May 2024 21:11:21 -0300 Subject: [PATCH 36/75] Inline string functions --- src/Makefile.am | 1 - src/utils/string.cc | 239 -------------------------------------------- src/utils/string.h | 211 ++++++++++++++++++++++++++++++++++---- 3 files changed, 193 insertions(+), 258 deletions(-) delete mode 100644 src/utils/string.cc diff --git a/src/Makefile.am b/src/Makefile.am index cf5549e7..ef9357aa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -253,7 +253,6 @@ UTILS = \ utils/random.cc \ utils/regex.cc \ utils/sha1.cc \ - utils/string.cc \ utils/system.cc \ utils/shared_files.cc diff --git a/src/utils/string.cc b/src/utils/string.cc deleted file mode 100644 index 195d5a1b..00000000 --- a/src/utils/string.cc +++ /dev/null @@ -1,239 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/) - * - * You may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * If any of the files related to licensing are missing or if you have any - * other questions related to licensing please contact Trustwave Holdings, Inc. - * directly using the email address security@modsecurity.org. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if defined _MSC_VER -#include -#elif defined __GNUC__ -#include -#include -#endif - -#include "modsecurity/modsecurity.h" - -#include "src/utils/string.h" - - -namespace modsecurity { -namespace utils { -namespace string { - - -std::string parserSanitizer(std::string a) { - a = removeWhiteSpacesIfNeeded(a); - a = removeBracketsIfNeeded(a); - return a; -} - - -std::string removeWhiteSpacesIfNeeded(std::string a) { - while (a.size() > 1 && a.at(0) == ' ') { - a.erase(0, 1); - } - while (a.size() > 1 && a.at(a.length()-1) == ' ') { - a.pop_back(); - } - return a; -} - - -std::string ascTime(time_t *t) { - std::string ts = std::ctime(t); - ts.pop_back(); - return ts; -} - - -std::string dash_if_empty(const std::string *str) { - if (str == NULL || str->empty()) { - return "-"; - } - - return *str; -} - - -std::string dash_if_empty(const char *str) { - if (str == NULL || strlen(str) == 0) { - return "-"; - } - - return std::string(str); -} - - -std::string limitTo(int amount, const std::string &str) { - std::string ret; - - if (str.length() > amount) { - ret.assign(str, 0, amount); - ret = ret + " (" + std::to_string(str.length() - amount) + " " \ - "characters omitted)"; - return ret; - } - - return str; -} - - -std::string removeBracketsIfNeeded(std::string a) { - if (a.length() > 1 && a.at(0) == '"' && a.at(a.length()-1) == '"') { - a.pop_back(); - a.erase(0, 1); - } - if (a.length() > 1 && a.at(0) == '\'' && a.at(a.length()-1) == '\'') { - a.pop_back(); - a.erase(0, 1); - } - return a; -} - - -std::string string_to_hex(const std::string& input) { - static const char* const lut = "0123456789ABCDEF"; - size_t len = input.length(); - - std::string output; - output.reserve(2 * len); - for (size_t i = 0; i < len; ++i) { - const unsigned char c = input[i]; - output.push_back(lut[c >> 4]); - output.push_back(lut[c & 15]); - } - return output; -} - -std::string toHexIfNeeded(const std::string &str, bool escape_spec) { - // escape_spec: escape special chars or not - // spec chars: '"' (quotation mark, ascii 34), '\' (backslash, ascii 92) - std::stringstream res; - - for (int i = 0; i < str.size(); i++) { - int c = (unsigned char)str.at(i); - if (c < 32 || c > 126 || (escape_spec == true && (c == 34 || c == 92))) { - res << "\\x" << std::setw(2) << std::setfill('0') << std::hex << c; - } else { - res << str.at(i); - } - } - - return res.str(); -} - - -std::vector ssplit(std::string str, char delimiter) { - std::vector internal; - std::stringstream ss(str); // Turn the string into a stream. - std::string tok; - - while (getline(ss, tok, delimiter)) { - internal.push_back(tok); - } - - return internal; -} - - -std::pair ssplit_pair(const std::string& str, char delimiter) { - std::stringstream ss(str); // Turn the string into a stream. - std::string key; - std::string value; - - getline(ss, key, delimiter); - if (key.length() < str.length()) { - value = str.substr(key.length()+1); - } - - return std::make_pair(key, value); -} - - -std::vector split(std::string str, char delimiter) { - std::vector internal = ssplit(str, delimiter); - - if (internal.size() == 0) { - internal.push_back(str); - } - - return internal; -} - - -void chomp(std::string *str) { - std::string::size_type pos = str->find_last_not_of("\n\r"); - if (pos != std::string::npos) { - str->erase(pos+1, str->length()-pos-1); - } -} - - -unsigned char x2c(const unsigned char *what) { - unsigned char digit; - - digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); - digit *= 16; - digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); - - return digit; -} - - -/** - * Converts a single hexadecimal digit into a decimal value. - */ -unsigned char xsingle2c(const unsigned char *what) { - unsigned char digit; - - digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); - - return digit; -} - - -unsigned char *c2x(unsigned what, unsigned char *where) { - static const char c2x_table[] = "0123456789abcdef"; - - what = what & 0xff; - *where++ = c2x_table[what >> 4]; - *where++ = c2x_table[what & 0x0f]; - - return where; -} - - -void replaceAll(std::string &str, std::string_view from, - std::string_view to) { - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); - } -} - -} // namespace string -} // namespace utils -} // namespace modsecurity diff --git a/src/utils/string.h b/src/utils/string.h index 54136e49..d6495012 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -15,9 +15,12 @@ #include #include +#include #include #include #include +#include +#include #ifndef SRC_UTILS_STRING_H_ #define SRC_UTILS_STRING_H_ @@ -56,25 +59,197 @@ const char HEX2DEC[256] = { }; -std::string ascTime(time_t *t); -std::string dash_if_empty(const char *str); -std::string dash_if_empty(const std::string *str); -std::string limitTo(int amount, const std::string &str); -std::string removeBracketsIfNeeded(std::string a); -std::string string_to_hex(const std::string& input); -std::string toHexIfNeeded(const std::string &str, bool escape_spec = false); -std::vector ssplit(std::string str, char delimiter); -std::pair ssplit_pair(const std::string& str, char delimiter); -std::vector split(std::string str, char delimiter); -void chomp(std::string *str); -void replaceAll(std::string &str, std::string_view from, - std::string_view to); -std::string removeWhiteSpacesIfNeeded(std::string a); -std::string parserSanitizer(std::string a); +inline std::string ascTime(time_t *t) { + std::string ts = std::ctime(t); + ts.pop_back(); + return ts; +} -unsigned char x2c(const unsigned char *what); -unsigned char xsingle2c(const unsigned char *what); -unsigned char *c2x(unsigned what, unsigned char *where); + +inline std::string dash_if_empty(const std::string *str) { + if (str == NULL || str->empty()) { + return "-"; + } + + return *str; +} + + +inline std::string dash_if_empty(const char *str) { + if (str == NULL || std::strlen(str) == 0) { + return "-"; + } + + return std::string(str); +} + + +inline std::string limitTo(int amount, const std::string &str) { + std::string ret; + + if (str.length() > amount) { + ret.assign(str, 0, amount); + ret = ret + " (" + std::to_string(str.length() - amount) + " " \ + "characters omitted)"; + return ret; + } + + return str; +} + + +inline std::string toHexIfNeeded(const std::string &str, bool escape_spec = false) { + // escape_spec: escape special chars or not + // spec chars: '"' (quotation mark, ascii 34), '\' (backslash, ascii 92) + std::stringstream res; + + for (int i = 0; i < str.size(); i++) { + int c = (unsigned char)str.at(i); + if (c < 32 || c > 126 || (escape_spec == true && (c == 34 || c == 92))) { + res << "\\x" << std::setw(2) << std::setfill('0') << std::hex << c; + } else { + res << str.at(i); + } + } + + return res.str(); +} + + +inline std::vector ssplit(std::string str, char delimiter) { + std::vector internal; + std::stringstream ss(str); // Turn the string into a stream. + std::string tok; + + while (getline(ss, tok, delimiter)) { + internal.push_back(tok); + } + + return internal; +} + + +inline std::pair ssplit_pair(const std::string& str, char delimiter) { + std::stringstream ss(str); // Turn the string into a stream. + std::string key; + std::string value; + + getline(ss, key, delimiter); + if (key.length() < str.length()) { + value = str.substr(key.length()+1); + } + + return std::make_pair(key, value); +} + + +inline std::vector split(std::string str, char delimiter) { + std::vector internal = ssplit(str, delimiter); + + if (internal.size() == 0) { + internal.push_back(str); + } + + return internal; +} + + +inline void chomp(std::string *str) { + std::string::size_type pos = str->find_last_not_of("\n\r"); + if (pos != std::string::npos) { + str->erase(pos+1, str->length()-pos-1); + } +} + + +inline void replaceAll(std::string &str, std::string_view from, + std::string_view to) { + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } +} + + +inline std::string removeWhiteSpacesIfNeeded(std::string a) { + while (a.size() > 1 && a.at(0) == ' ') { + a.erase(0, 1); + } + while (a.size() > 1 && a.at(a.length()-1) == ' ') { + a.pop_back(); + } + return a; +} + + +inline std::string removeBracketsIfNeeded(std::string a) { + if (a.length() > 1 && a.at(0) == '"' && a.at(a.length()-1) == '"') { + a.pop_back(); + a.erase(0, 1); + } + if (a.length() > 1 && a.at(0) == '\'' && a.at(a.length()-1) == '\'') { + a.pop_back(); + a.erase(0, 1); + } + return a; +} + + +inline std::string parserSanitizer(std::string a) { + a = removeWhiteSpacesIfNeeded(a); + a = removeBracketsIfNeeded(a); + return a; +} + + +inline unsigned char x2c(const unsigned char *what) { + unsigned char digit; + + digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); + digit *= 16; + digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); + + return digit; +} + + +/** + * Converts a single hexadecimal digit into a decimal value. + */ +inline unsigned char xsingle2c(const unsigned char *what) { + unsigned char digit; + + digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); + + return digit; +} + + +inline unsigned char *c2x(unsigned what, unsigned char *where) { + static const char c2x_table[] = "0123456789abcdef"; + + what = what & 0xff; + *where++ = c2x_table[what >> 4]; + *where++ = c2x_table[what & 0x0f]; + + return where; +} + + +inline std::string string_to_hex(const std::string& input) { + static const char* const lut = "0123456789ABCDEF"; + size_t len = input.length(); + + std::string output; + output.reserve(2 * len); + for (size_t i = 0; i < len; ++i) { + const unsigned char c = input[i]; + output.push_back(lut[c >> 4]); + output.push_back(lut[c & 15]); + } + return output; +} template From cc0f893854545404b7b7172dcacfe26aab13e38c Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 9 Aug 2024 14:02:40 -0700 Subject: [PATCH 37/75] Removed unused overload of dash_if_empty that sonarcloud flags as potential buffer overflow --- src/transaction.cc | 4 ++-- src/utils/string.h | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/transaction.cc b/src/transaction.cc index 7dc8ba24..bf24e2ad 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -1520,7 +1520,7 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, ss << utils::string::dash_if_empty( m_variableRequestHeaders.resolveFirst("Host").get()) << " "; - ss << utils::string::dash_if_empty(this->m_clientIpAddress->c_str()) << " "; + ss << utils::string::dash_if_empty(this->m_clientIpAddress.get()) << " "; /** TODO: Check variable */ variables::RemoteUser *r = new variables::RemoteUser("REMOTE_USER"); std::vector l; @@ -1531,7 +1531,7 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, delete r; ss << utils::string::dash_if_empty( - m_variableRemoteUser.c_str()); + &m_variableRemoteUser); ss << " "; /** TODO: Check variable */ //ss << utils::string::dash_if_empty( diff --git a/src/utils/string.h b/src/utils/string.h index d6495012..eaacffe5 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -75,15 +75,6 @@ inline std::string dash_if_empty(const std::string *str) { } -inline std::string dash_if_empty(const char *str) { - if (str == NULL || std::strlen(str) == 0) { - return "-"; - } - - return std::string(str); -} - - inline std::string limitTo(int amount, const std::string &str) { std::string ret; From eb26b7960ce7389359d63b37572d4509fb7abd9d Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Mon, 12 Aug 2024 18:46:19 +0200 Subject: [PATCH 38/75] Fix regression test result; Add test to main test-suite list --- test/test-cases/regression/fn-setHostname.json | 2 +- test/test-suite.in | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test-cases/regression/fn-setHostname.json b/test/test-cases/regression/fn-setHostname.json index 33d90695..59c5b52e 100644 --- a/test/test-cases/regression/fn-setHostname.json +++ b/test/test-cases/regression/fn-setHostname.json @@ -29,7 +29,7 @@ ] }, "expected":{ - "http_code": 200, + "http_code": 403, "debug_log": "[hostname: \"modsecurity.org\"]" }, "rules":[ diff --git a/test/test-suite.in b/test/test-suite.in index eee696ec..0feb361b 100644 --- a/test/test-suite.in +++ b/test/test-suite.in @@ -49,6 +49,7 @@ TESTS+=test/test-cases/regression/config-update-target-by-tag.json TESTS+=test/test-cases/regression/config-xml_external_entity.json TESTS+=test/test-cases/regression/debug_log.json TESTS+=test/test-cases/regression/directive-sec_rule_script.json +TESTS+=test/test-cases/regression/fn-setHostname.json TESTS+=test/test-cases/regression/issue-1152.json TESTS+=test/test-cases/regression/issue-1528.json TESTS+=test/test-cases/regression/issue-1565.json From 77adb57524ccf803396d9d5cb3f3c17383cc0ccb Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 12 Aug 2024 06:18:20 -0700 Subject: [PATCH 39/75] Avoid std::string copy in ssplit argument - Other minor changes reported by sonarcloud --- src/request_body_processor/multipart.cc | 4 +-- src/utils/string.h | 38 ++++++++++++------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index 93df5e7f..c578638b 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -855,7 +855,7 @@ int Multipart::process_part_header(std::string *error, int offset) { } new_value = std::string(data); - utils::string::chomp(&new_value); + utils::string::chomp(new_value); /* update the header value in the table */ header_value = m_mpp->m_headers.at( @@ -924,7 +924,7 @@ int Multipart::process_part_header(std::string *error, int offset) { i++; } header_value = std::string(data); - utils::string::chomp(&header_value); + utils::string::chomp(header_value); /* error if the name already exists */ if (m_mpp->m_headers.count(header_name) > 0) { diff --git a/src/utils/string.h b/src/utils/string.h index eaacffe5..700f33b9 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -59,7 +59,7 @@ const char HEX2DEC[256] = { }; -inline std::string ascTime(time_t *t) { +inline std::string ascTime(const time_t *t) { std::string ts = std::ctime(t); ts.pop_back(); return ts; @@ -67,7 +67,7 @@ inline std::string ascTime(time_t *t) { inline std::string dash_if_empty(const std::string *str) { - if (str == NULL || str->empty()) { + if (str == nullptr || str->empty()) { return "-"; } @@ -107,7 +107,7 @@ inline std::string toHexIfNeeded(const std::string &str, bool escape_spec = fals } -inline std::vector ssplit(std::string str, char delimiter) { +inline std::vector ssplit(const std::string &str, char delimiter) { std::vector internal; std::stringstream ss(str); // Turn the string into a stream. std::string tok; @@ -134,10 +134,10 @@ inline std::pair ssplit_pair(const std::string& str, c } -inline std::vector split(std::string str, char delimiter) { +inline std::vector split(const std::string &str, char delimiter) { std::vector internal = ssplit(str, delimiter); - if (internal.size() == 0) { + if (internal.empty()) { internal.push_back(str); } @@ -145,10 +145,10 @@ inline std::vector split(std::string str, char delimiter) { } -inline void chomp(std::string *str) { - std::string::size_type pos = str->find_last_not_of("\n\r"); +inline void chomp(std::string &str) { + std::string::size_type pos = str.find_last_not_of("\n\r"); if (pos != std::string::npos) { - str->erase(pos+1, str->length()-pos-1); + str.erase(pos+1, str.length()-pos-1); } } @@ -194,17 +194,6 @@ inline std::string parserSanitizer(std::string a) { } -inline unsigned char x2c(const unsigned char *what) { - unsigned char digit; - - digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); - digit *= 16; - digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); - - return digit; -} - - /** * Converts a single hexadecimal digit into a decimal value. */ @@ -217,6 +206,17 @@ inline unsigned char xsingle2c(const unsigned char *what) { } +inline unsigned char x2c(const unsigned char *what) { + unsigned char digit; + + digit = xsingle2c(what); + digit *= 16; + digit += xsingle2c(what+1); + + return digit; +} + + inline unsigned char *c2x(unsigned what, unsigned char *where) { static const char c2x_table[] = "0123456789abcdef"; From 6388d88f389973fbe241891a8c1b1c95f894d9dc Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Tue, 13 Aug 2024 18:26:18 +0200 Subject: [PATCH 40/75] Check if the MP header contains invalid character --- src/request_body_processor/multipart.cc | 12 +++++ .../request-body-parser-multipart.json | 51 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index d9ed6c6d..15a35965 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -918,6 +918,18 @@ int Multipart::process_part_header(std::string *error, int offset) { return false; } + /* check if multipart header contains any invalid characters */ + for (const auto& ch : header_name) { + if (ch < 33 || ch > 126) { + ms_dbg_a(m_transaction, 1, + "Multipart: Invalid part header " \ + "(contains invalid character)."); + error->assign("Multipart: Invalid part header "\ + "(contains invalid character)."); + return false; + } + } + /* extract the value value */ data++; i++; diff --git a/test/test-cases/regression/request-body-parser-multipart.json b/test/test-cases/regression/request-body-parser-multipart.json index c9220573..4e25168e 100644 --- a/test/test-cases/regression/request-body-parser-multipart.json +++ b/test/test-cases/regression/request-body-parser-multipart.json @@ -3294,5 +3294,56 @@ "SecRequestBodyAccess On", "SecRule ARGS:namea \"@streq 111\" \"phase:2,deny,id:500096\"" ] + }, + { + "enabled":1, + "version_min":300000, + "title":"multipart parser (invalid part header - contains invalid character)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=a", + "Expect":"100-continue" + }, + "uri":"/", + "method":"POST", + "body":[ + "--a\r", + "\u000eContent-Disposition\u000e: form-data; name=\"file\"; filename=\"1.jsp\"\r", + "Content-Disposition: form-data; name=\"post\";\r", + "\r", + "<%out.print(123)%>\r", + "--a--\r" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "http_code":403, + "debug_log":"Multipart: Invalid part header \\(contains invalid character\\)" + }, + "rules":[ + "SecruleEngine On", + "SecRule REQBODY_PROCESSOR_ERROR \"@eq 1\" \"phase:2,deny,status:403,id:500077\"" + ] } ] From 8d6b185856b9a5dc02548a5d06c1850570c00dd3 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 9 Aug 2024 09:41:37 -0700 Subject: [PATCH 41/75] Removed unnecessary lock to call acmp_process_quick in Pm::evaluate - This was introduced in commit 119a6fc & 7d786b3 because of a potential issue reported in #1573. - The ACMP tree structure is initialized when the operator is initialized. - During transaction execution the ACMP tree structure is only 'read' while traversing the tree (in acmp_process_quick) so this is safe for use in a multi-threaded environment. --- configure.ac | 17 ----------------- src/Makefile.am | 1 - src/operators/pm.cc | 7 ------- src/operators/pm.h | 6 ------ 4 files changed, 31 deletions(-) diff --git a/configure.ac b/configure.ac index 34281a3f..11cef0b6 100644 --- a/configure.ac +++ b/configure.ac @@ -316,23 +316,6 @@ AC_ARG_ENABLE(parser-generation, [buildParser=false] ) -# Mutex -AC_ARG_ENABLE(mutex-on-pm, - [AS_HELP_STRING([--enable-mutex-on-pm],[Treats pm operations as a critical section])], - - [case "${enableval}" in - yes) mutexPm=true ;; - no) mutexPm=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-mutex-on-pm) ;; - esac], - - [mutexPm=false] - ) -if test "$mutexPm" == "true"; then - MODSEC_MUTEX_ON_PM="-DMUTEX_ON_PM=1" - AC_SUBST(MODSEC_MUTEX_ON_PM) -fi - if test $buildParser = true; then AC_PROG_YACC diff --git a/src/Makefile.am b/src/Makefile.am index ef9357aa..6f358655 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -321,7 +321,6 @@ libmodsecurity_la_CPPFLAGS = \ $(GEOIP_CFLAGS) \ $(GLOBAL_CPPFLAGS) \ $(MODSEC_NO_LOGS) \ - $(MODSEC_MUTEX_ON_PM) \ $(YAJL_CFLAGS) \ $(LMDB_CFLAGS) \ $(PCRE_CFLAGS) \ diff --git a/src/operators/pm.cc b/src/operators/pm.cc index d92fc163..ba7039bf 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -85,14 +85,7 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, pt.parser = m_p; pt.ptr = NULL; const char *match = NULL; -#ifdef MODSEC_MUTEX_ON_PM - { - const std::lock_guard lock(m_mutex); -#endif rc = acmp_process_quick(&pt, &match, input.c_str(), input.length()); -#ifdef MODSEC_MUTEX_ON_PM - } -#endif if (rc >= 0 && transaction) { std::string match_(match?match:""); diff --git a/src/operators/pm.h b/src/operators/pm.h index ed5649af..d07ba46c 100644 --- a/src/operators/pm.h +++ b/src/operators/pm.h @@ -53,12 +53,6 @@ class Pm : public Operator { protected: ACMP *m_p; - -#ifdef MODSEC_MUTEX_ON_PM - - private: - std::mutex m_mutex; -#endif }; From 5e6fcbc60b378cb2901ebf24b024bce6978b6c96 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 12 Aug 2024 07:58:06 -0700 Subject: [PATCH 42/75] Replace usage of std::ctime, which is not safe for use in multithreaded contexts - std::ctime returns a pointer to a string that "may be shared between std::asctime and std::ctime, and may be overwritten on each invocation of any of those functions.". - https://en.cppreference.com/w/cpp/chrono/c/ctime - Replaced with call to strftime to generate the same string representation (using the format string: %c) - Leveraged localtime_r (which is thread-safe) to convert time_t to struct tm, as required by strftime. --- src/utils/string.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/utils/string.h b/src/utils/string.h index 700f33b9..b0c3c17d 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -21,6 +21,11 @@ #include #include #include +#include + +#ifdef WIN32 +#include "src/compat/msvc.h" +#endif #ifndef SRC_UTILS_STRING_H_ #define SRC_UTILS_STRING_H_ @@ -60,9 +65,11 @@ const char HEX2DEC[256] = { inline std::string ascTime(const time_t *t) { - std::string ts = std::ctime(t); - ts.pop_back(); - return ts; + struct tm timeinfo; + localtime_r(t, &timeinfo); + char tstr[std::size("Www Mmm dd hh:mm:ss yyyy")]; + strftime(tstr, std::size(tstr), "%c", &timeinfo); + return tstr; } From 23a341eb6a0d53148961ad412e3da7a12495523b Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 12 Aug 2024 08:47:04 -0700 Subject: [PATCH 43/75] Calculate sizes of strftime buffers based on format strings - Leverage std::size to determine buffer size at compile time. - Simplified 'TimeMon::evaluate' implementation as it was using strftime to get the month, convert the string to int, and then decrement it by one to make it zero based. This same value is already available in the 'struct tm' previously generated with the call to localtime_r (and where the month is already zero-based) --- src/audit_log/writer/parallel.cc | 23 +++++++++++------------ src/request_body_processor/multipart.cc | 6 +++--- src/transaction.cc | 15 +++++++-------- src/variables/time.cc | 8 +++----- src/variables/time_day.cc | 9 ++++----- src/variables/time_hour.cc | 9 ++++----- src/variables/time_min.cc | 9 ++++----- src/variables/time_mon.cc | 10 ++-------- src/variables/time_sec.cc | 9 ++++----- src/variables/time_wday.cc | 9 ++++----- src/variables/time_year.cc | 9 ++++----- 11 files changed, 50 insertions(+), 66 deletions(-) diff --git a/src/audit_log/writer/parallel.cc b/src/audit_log/writer/parallel.cc index d23e7958..5237adb7 100644 --- a/src/audit_log/writer/parallel.cc +++ b/src/audit_log/writer/parallel.cc @@ -51,28 +51,27 @@ Parallel::~Parallel() { inline std::string Parallel::logFilePath(time_t *t, int part) { - struct tm timeinfo; - char tstr[300]; - std::string name(""); + std::string name; + struct tm timeinfo; localtime_r(t, &timeinfo); if (part & YearMonthDayDirectory) { - memset(tstr, '\0', 300); - strftime(tstr, 299, "/%Y%m%d", &timeinfo); - name = tstr; + char tstr[std::size("/yyyymmdd")]; + strftime(tstr, std::size(tstr), "/%Y%m%d", &timeinfo); + name.append(tstr); } if (part & YearMonthDayAndTimeDirectory) { - memset(tstr, '\0', 300); - strftime(tstr, 299, "/%Y%m%d-%H%M", &timeinfo); - name = name + tstr; + char tstr[std::size("/yyyymmdd-hhmm")]; + strftime(tstr, std::size(tstr), "/%Y%m%d-%H%M", &timeinfo); + name.append(tstr); } if (part & YearMonthDayAndTimeFileName) { - memset(tstr, '\0', 300); - strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo); - name = name + tstr; + char tstr[std::size("/yyyymmdd-hhmmss")]; + strftime(tstr, std::size(tstr), "/%Y%m%d-%H%M%S", &timeinfo); + name.append(tstr); } return name; diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index c578638b..9a20b051 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -65,12 +65,12 @@ MultipartPartTmpFile::~MultipartPartTmpFile() { } void MultipartPartTmpFile::Open() { - struct tm timeinfo; - time_t tt = time(NULL); + time_t tt = time(nullptr); + struct tm timeinfo; localtime_r(&tt, &timeinfo); - char tstr[17]; + char tstr[std::size("/yyyymmdd-hhmmss")]; strftime(tstr, std::size(tstr), "/%Y%m%d-%H%M%S", &timeinfo); std::string path = m_transaction->m_rules->m_uploadDirectory.m_value; diff --git a/src/transaction.cc b/src/transaction.cc index bf24e2ad..f69df188 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -1509,13 +1509,12 @@ bool Transaction::intervention(ModSecurityIntervention *it) { std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, double size, const std::string &md5) { std::stringstream ss; - struct tm timeinfo; - char tstr[300]; - memset(tstr, '\0', 300); + struct tm timeinfo; localtime_r(&this->m_timeStamp, &timeinfo); - strftime(tstr, 299, "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); + char tstr[std::size("[dd/Mmm/yyyy:hh:mm:ss shhmm]")]; + strftime(tstr, std::size(tstr), "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); ss << utils::string::dash_if_empty( m_variableRequestHeaders.resolveFirst("Host").get()) @@ -1572,14 +1571,14 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, std::string Transaction::toOldAuditLogFormat(int parts, const std::string &trailer) { std::stringstream audit_log; - struct tm timeinfo; - char tstr[300]; - memset(tstr, '\0', 300); + struct tm timeinfo; localtime_r(&this->m_timeStamp, &timeinfo); + char tstr[std::size("[dd/Mmm/yyyy:hh:mm:ss shhmm]")]; + strftime(tstr, std::size(tstr), "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); + audit_log << "--" << trailer << "-" << "A--" << std::endl; - strftime(tstr, 299, "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); audit_log << tstr; audit_log << " " << m_id->c_str(); audit_log << " " << this->m_clientIpAddress->c_str(); diff --git a/src/variables/time.cc b/src/variables/time.cc index 7d481ee6..c674f4e0 100644 --- a/src/variables/time.cc +++ b/src/variables/time.cc @@ -40,15 +40,13 @@ namespace variables { void Time::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); + + char tstr[std::size("hh:mm:ss")]; strftime(tstr, 200, "%H:%M:%S", &timeinfo); transaction->m_variableTime.assign(tstr); diff --git a/src/variables/time_day.cc b/src/variables/time_day.cc index f094d4c9..eefe937f 100644 --- a/src/variables/time_day.cc +++ b/src/variables/time_day.cc @@ -40,15 +40,14 @@ namespace variables { void TimeDay::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%d", &timeinfo); + + char tstr[std::size("dd")]; + strftime(tstr, std::size(tstr), "%d", &timeinfo); transaction->m_variableTimeDay.assign(tstr); diff --git a/src/variables/time_hour.cc b/src/variables/time_hour.cc index ab809ead..1a9c1bf7 100644 --- a/src/variables/time_hour.cc +++ b/src/variables/time_hour.cc @@ -40,15 +40,14 @@ namespace variables { void TimeHour::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%H", &timeinfo); + + char tstr[std::size("hh")]; + strftime(tstr, std::size(tstr), "%H", &timeinfo); transaction->m_variableTimeHour.assign(tstr); diff --git a/src/variables/time_min.cc b/src/variables/time_min.cc index 9d03be4d..134582de 100644 --- a/src/variables/time_min.cc +++ b/src/variables/time_min.cc @@ -40,15 +40,14 @@ namespace variables { void TimeMin::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%M", &timeinfo); + + char tstr[std::size("mm")]; + strftime(tstr, std::size(tstr), "%M", &timeinfo); transaction->m_variableTimeMin.assign(tstr); diff --git a/src/variables/time_mon.cc b/src/variables/time_mon.cc index 17e74f31..18059112 100644 --- a/src/variables/time_mon.cc +++ b/src/variables/time_mon.cc @@ -40,19 +40,13 @@ namespace variables { void TimeMon::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%m", &timeinfo); - int a = atoi(tstr); - a--; - transaction->m_variableTimeMin.assign(std::to_string(a)); + transaction->m_variableTimeMin.assign(std::to_string(timeinfo.tm_mon)); l->push_back(new VariableValue(&m_retName, &transaction->m_variableTimeMin)); diff --git a/src/variables/time_sec.cc b/src/variables/time_sec.cc index 5e39af7f..a9604771 100644 --- a/src/variables/time_sec.cc +++ b/src/variables/time_sec.cc @@ -40,15 +40,14 @@ namespace variables { void TimeSec::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%S", &timeinfo); + + char tstr[std::size("ss")]; + strftime(tstr, std::size(tstr), "%S", &timeinfo); transaction->m_variableTimeSec.assign(tstr); diff --git a/src/variables/time_wday.cc b/src/variables/time_wday.cc index fd6a0278..e1840f58 100644 --- a/src/variables/time_wday.cc +++ b/src/variables/time_wday.cc @@ -40,15 +40,14 @@ namespace variables { void TimeWDay::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%u", &timeinfo); + + char tstr[std::size("d")]; + strftime(tstr, std::size(tstr), "%u", &timeinfo); transaction->m_variableTimeWDay.assign(tstr); diff --git a/src/variables/time_year.cc b/src/variables/time_year.cc index f68e8cd6..a8f1a502 100644 --- a/src/variables/time_year.cc +++ b/src/variables/time_year.cc @@ -40,15 +40,14 @@ namespace variables { void TimeYear::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%Y", &timeinfo); + + char tstr[std::size("yyyy")]; + strftime(tstr, std::size(tstr), "%Y", &timeinfo); transaction->m_variableTimeYear.assign(tstr); From ee5f95eb04d52a316ae7424e36f3cce64ab1c230 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 9 Aug 2024 06:54:35 -0700 Subject: [PATCH 44/75] Added support to run unit tests in a multithreaded context - This is controlled by specifying the 'mtstress' argument when running `unit_test`. - The goal is to detect if the operator/transformation fails in this context. - In this mode, the test will be executed 5'000 times in 50 threads concurrently. - Allocation & initialization of the operator/transformation is performed once in the main thread, while the evaluation is executed in the threads. - This is consistent with the library's support for multithreading, where initialization and loading of rules is expected to run once. See issue #3215. --- test/common/modsecurity_test.cc | 19 ++-- test/common/modsecurity_test.h | 8 +- test/unit/unit.cc | 190 +++++++++++++++++++++++--------- test/unit/unit_test.cc | 8 +- test/unit/unit_test.h | 9 +- 5 files changed, 165 insertions(+), 69 deletions(-) diff --git a/test/common/modsecurity_test.cc b/test/common/modsecurity_test.cc index 22757191..0f769054 100644 --- a/test/common/modsecurity_test.cc +++ b/test/common/modsecurity_test.cc @@ -93,13 +93,13 @@ bool ModSecurityTest::load_test_json(const std::string &file) { template -std::pair>* +void ModSecurityTest::load_tests(const std::string &path) { DIR *dir; struct dirent *ent; struct stat buffer; - if ((dir = opendir(path.c_str())) == NULL) { + if ((dir = opendir(path.c_str())) == nullptr) { /* if target is a file, use it as a single test. */ if (stat(path.c_str(), &buffer) == 0) { if (load_test_json(path) == false) { @@ -107,10 +107,10 @@ ModSecurityTest::load_tests(const std::string &path) { std::cout << std::endl; } } - return NULL; + return; } - while ((ent = readdir(dir)) != NULL) { + while ((ent = readdir(dir)) != nullptr) { std::string filename = ent->d_name; std::string json = ".json"; if (filename.size() < json.size() @@ -123,16 +123,15 @@ ModSecurityTest::load_tests(const std::string &path) { } } closedir(dir); - - return NULL; } template -std::pair>* ModSecurityTest::load_tests() { - return load_tests(this->target); +void ModSecurityTest::load_tests() { + load_tests(this->target); } + template void ModSecurityTest::cmd_options(int argc, char **argv) { int i = 1; @@ -144,6 +143,10 @@ void ModSecurityTest::cmd_options(int argc, char **argv) { i++; m_count_all = true; } + if (argc > i && strcmp(argv[i], "mtstress") == 0) { + i++; + m_test_multithreaded = true; + } if (std::getenv("AUTOMAKE_TESTS")) { m_automake_output = true; } diff --git a/test/common/modsecurity_test.h b/test/common/modsecurity_test.h index 79a168f7..8b55a16c 100644 --- a/test/common/modsecurity_test.h +++ b/test/common/modsecurity_test.h @@ -34,12 +34,13 @@ template class ModSecurityTest : ModSecurityTest() : m_test_number(0), m_automake_output(false), - m_count_all(false) { } + m_count_all(false), + m_test_multithreaded(false) { } std::string header(); void cmd_options(int, char **); - std::pair>* load_tests(); - std::pair>* load_tests(const std::string &path); + void load_tests(); + void load_tests(const std::string &path); bool load_test_json(const std::string &file); std::string target; @@ -48,6 +49,7 @@ template class ModSecurityTest : int m_test_number; bool m_automake_output; bool m_count_all; + bool m_test_multithreaded; }; } // namespace modsecurity_test diff --git a/test/unit/unit.cc b/test/unit/unit.cc index 46013ec7..7b62e7f7 100644 --- a/test/unit/unit.cc +++ b/test/unit/unit.cc @@ -15,7 +15,9 @@ #include #include - +#include +#include +#include #include #include #include @@ -38,6 +40,7 @@ using modsecurity_test::UnitTest; +using modsecurity_test::UnitTestResult; using modsecurity_test::ModSecurityTest; using modsecurity_test::ModSecurityTestResults; using modsecurity::actions::transformations::Transformation; @@ -53,64 +56,149 @@ void print_help() { } -void perform_unit_test(ModSecurityTest *test, UnitTest *t, - ModSecurityTestResults* res) { - std::string error; +struct OperatorTest { + using ItemType = Operator; + + static ItemType* init(const UnitTest &t) { + auto op = Operator::instantiate(t.name, t.param); + assert(op != nullptr); + + std::string error; + op->init(t.filename, &error); + + return op; + } + + static UnitTestResult eval(ItemType &op, const UnitTest &t) { + return {op.evaluate(nullptr, nullptr, t.input, nullptr), {}}; + } + + static bool check(const UnitTestResult &result, const UnitTest &t) { + return result.ret != t.ret; + } +}; + + +struct TransformationTest { + using ItemType = Transformation; + + static ItemType* init(const UnitTest &t) { + auto tfn = Transformation::instantiate("t:" + t.name); + assert(tfn != nullptr); + + return tfn; + } + + static UnitTestResult eval(ItemType &tfn, const UnitTest &t) { + return {1, tfn.evaluate(t.input, nullptr)}; + } + + static bool check(const UnitTestResult &result, const UnitTest &t) { + return result.output != t.output; + } +}; + + +template +UnitTestResult perform_unit_test_once(const UnitTest &t) { + std::unique_ptr item(TestType::init(t)); + assert(item.get() != nullptr); + + return TestType::eval(*item.get(), t); +} + + +template +UnitTestResult perform_unit_test_multithreaded(const UnitTest &t) { + + constexpr auto NUM_THREADS = 50; + constexpr auto ITERATIONS = 5'000; + + std::array threads; + std::array results; + + std::unique_ptr item(TestType::init(t)); + assert(item.get() != nullptr); + + for (auto i = 0; i != threads.size(); ++i) + { + auto &result = results[i]; + threads[i] = std::thread( + [&item, &t, &result]() + { + for (auto j = 0; j != ITERATIONS; ++j) + result = TestType::eval(*item.get(), t); + }); + } + + UnitTestResult ret; + + for (auto i = 0; i != threads.size(); ++i) + { + threads[i].join(); + if (TestType::check(results[i], t)) + ret = results[i]; // error value, keep iterating to join all threads + else if(i == 0) + ret = results[i]; // initial value + } + + return ret; // cppcheck-suppress uninitvar ; false positive, ret assigned at least once in previous loop +} + + +template +void perform_unit_test_helper(const ModSecurityTest &test, UnitTest &t, + ModSecurityTestResults &res) { + + if (!test.m_test_multithreaded) + t.result = perform_unit_test_once(t); + else + t.result = perform_unit_test_multithreaded(t); + + if (TestType::check(t.result, t)) { + res.push_back(&t); + if (test.m_automake_output) { + std::cout << "FAIL "; + } + } else if (test.m_automake_output) { + std::cout << "PASS "; + } +} + + +void perform_unit_test(const ModSecurityTest &test, UnitTest &t, + ModSecurityTestResults &res) { bool found = true; - if (test->m_automake_output) { + if (test.m_automake_output) { std::cout << ":test-result: "; } - if (t->resource.empty() == false) { - found = (std::find(resources.begin(), resources.end(), t->resource) - != resources.end()); + if (t.resource.empty() == false) { + found = std::find(resources.begin(), resources.end(), t.resource) + != resources.end(); } if (!found) { - t->skipped = true; - res->push_back(t); - if (test->m_automake_output) { + t.skipped = true; + res.push_back(&t); + if (test.m_automake_output) { std::cout << "SKIP "; } } - if (t->type == "op") { - Operator *op = Operator::instantiate(t->name, t->param); - op->init(t->filename, &error); - int ret = op->evaluate(NULL, NULL, t->input, NULL); - t->obtained = ret; - if (ret != t->ret) { - res->push_back(t); - if (test->m_automake_output) { - std::cout << "FAIL "; - } - } else if (test->m_automake_output) { - std::cout << "PASS "; - } - delete op; - } else if (t->type == "tfn") { - Transformation *tfn = Transformation::instantiate("t:" + t->name); - std::string ret = tfn->evaluate(t->input, NULL); - t->obtained = 1; - t->obtainedOutput = ret; - if (ret != t->output) { - res->push_back(t); - if (test->m_automake_output) { - std::cout << "FAIL "; - } - } else if (test->m_automake_output) { - std::cout << "PASS "; - } - delete tfn; + if (t.type == "op") { + perform_unit_test_helper(test, t, res); + } else if (t.type == "tfn") { + perform_unit_test_helper(test, t, res); } else { - std::cerr << "Failed. Test type is unknown: << " << t->type; + std::cerr << "Failed. Test type is unknown: << " << t.type; std::cerr << std::endl; } - if (test->m_automake_output) { - std::cout << t->name << " " - << modsecurity::utils::string::toHexIfNeeded(t->input) + if (test.m_automake_output) { + std::cout << t.name << " " + << modsecurity::utils::string::toHexIfNeeded(t.input) << std::endl; } } @@ -151,17 +239,15 @@ int main(int argc, char **argv) { test.load_tests("test-cases/secrules-language-tests/transformations"); } - for (std::pair *> a : test) { - std::vector *tests = a.second; - + for (auto& [filename, tests] : test) { total += tests->size(); - for (UnitTest *t : *tests) { + for (auto t : *tests) { ModSecurityTestResults r; if (!test.m_automake_output) { - std::cout << " " << a.first << "...\t"; + std::cout << " " << filename << "...\t"; } - perform_unit_test(&test, t, &r); + perform_unit_test(test, *t, r); if (!test.m_automake_output) { int skp = 0; @@ -191,7 +277,7 @@ int main(int argc, char **argv) { std::cout << "Total >> " << total << std::endl; } - for (UnitTest *t : results) { + for (const auto t : results) { std::cout << t->print() << std::endl; } @@ -216,8 +302,8 @@ int main(int argc, char **argv) { } for (auto a : test) { - auto *vec = a.second; - for(auto *t : *vec) + auto vec = a.second; + for(auto t : *vec) delete t; delete vec; } diff --git a/test/unit/unit_test.cc b/test/unit/unit_test.cc index d15533a3..dee4f1ae 100644 --- a/test/unit/unit_test.cc +++ b/test/unit/unit_test.cc @@ -102,15 +102,15 @@ std::string UnitTest::print() { i << " \"param\": \"" << this->param << "\"" << std::endl; i << " \"output\": \"" << this->output << "\"" << std::endl; i << "}" << std::endl; - if (this->ret != this->obtained) { + if (this->ret != this->result.ret) { i << "Expecting: \"" << this->ret << "\" - returned: \""; - i << this->obtained << "\"" << std::endl; + i << this->result.ret << "\"" << std::endl; } - if (this->output != this->obtainedOutput) { + if (this->output != this->result.output) { i << "Expecting: \""; i << modsecurity::utils::string::toHexIfNeeded(this->output); i << "\" - returned: \""; - i << modsecurity::utils::string::toHexIfNeeded(this->obtainedOutput); + i << modsecurity::utils::string::toHexIfNeeded(this->result.output); i << "\""; i << std::endl; } diff --git a/test/unit/unit_test.h b/test/unit/unit_test.h index d200db5d..81d99d14 100644 --- a/test/unit/unit_test.h +++ b/test/unit/unit_test.h @@ -25,6 +25,12 @@ namespace modsecurity_test { +class UnitTestResult { + public: + int ret; + std::string output; +}; + class UnitTest { public: static UnitTest *from_yajl_node(const yajl_val &); @@ -39,9 +45,8 @@ class UnitTest { std::string filename; std::string output; int ret; - int obtained; int skipped; - std::string obtainedOutput; + UnitTestResult result; }; } // namespace modsecurity_test From 2cb1d032e3e99d5e502e467b610beaa32851a852 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Wed, 14 Aug 2024 08:46:30 -0700 Subject: [PATCH 45/75] Restore pthread LDFLAG. --- examples/multithread/Makefile.am | 1 + examples/reading_logs_with_offset/Makefile.am | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/multithread/Makefile.am b/examples/multithread/Makefile.am index 40e81dd1..c17b431a 100644 --- a/examples/multithread/Makefile.am +++ b/examples/multithread/Makefile.am @@ -21,6 +21,7 @@ multithread_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ + -lpthread \ -lm \ -lstdc++ \ $(LMDB_LDFLAGS) \ diff --git a/examples/reading_logs_with_offset/Makefile.am b/examples/reading_logs_with_offset/Makefile.am index 3ecda10c..f845c583 100644 --- a/examples/reading_logs_with_offset/Makefile.am +++ b/examples/reading_logs_with_offset/Makefile.am @@ -21,6 +21,7 @@ read_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ + -lpthread \ -lm \ -lstdc++ \ $(LMDB_LDFLAGS) \ From a5f223cb5217326177cb6a0df2f5e761b6239517 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Sat, 17 Aug 2024 22:36:30 +0000 Subject: [PATCH 46/75] Individual test result should not be printed for automake output - Test results output escape characters to highlight whether the test passed or failed. Additionally, the input & output for each test can include non-ASCII characters. These characters break parsing of results (.log & .trs files) with grep, as the files are interpreted to be binary. --- test/unit/unit.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/unit.cc b/test/unit/unit.cc index 7b62e7f7..75fec137 100644 --- a/test/unit/unit.cc +++ b/test/unit/unit.cc @@ -275,10 +275,10 @@ int main(int argc, char **argv) { if (!test.m_automake_output) { std::cout << "Total >> " << total << std::endl; - } - for (const auto t : results) { - std::cout << t->print() << std::endl; + for (const auto t : results) { + std::cout << t->print() << std::endl; + } } const int skp = std::count_if(results.cbegin(), results.cend(), [](const auto &i) From df081af870e2d2e3603ebdbb4390998715134cab Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 16 Aug 2024 05:59:38 -0700 Subject: [PATCH 47/75] Adjusted pthread LDFLAG in examples required for multithreading. - Some versions of gcc/libc require setting the pthread flag when using std::thread, which to implement it. - This was found compiling the library in a Debian (bullseye) container. --- examples/reading_logs_via_rule_message/Makefile.am | 1 + examples/reading_logs_with_offset/Makefile.am | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/reading_logs_via_rule_message/Makefile.am b/examples/reading_logs_via_rule_message/Makefile.am index 55d3a93f..210edef3 100644 --- a/examples/reading_logs_via_rule_message/Makefile.am +++ b/examples/reading_logs_via_rule_message/Makefile.am @@ -21,6 +21,7 @@ simple_request_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ + -lpthread \ -lm \ -lstdc++ \ $(LMDB_LDFLAGS) \ diff --git a/examples/reading_logs_with_offset/Makefile.am b/examples/reading_logs_with_offset/Makefile.am index f845c583..3ecda10c 100644 --- a/examples/reading_logs_with_offset/Makefile.am +++ b/examples/reading_logs_with_offset/Makefile.am @@ -21,7 +21,6 @@ read_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(LMDB_LDFLAGS) \ From 315b3d6e777f625d7e836a43f10903f1e33f4676 Mon Sep 17 00:00:00 2001 From: David Kirstein Date: Mon, 26 Aug 2024 08:38:48 +0200 Subject: [PATCH 48/75] Lua::run: Move logging of `str` parameter to higher log level. --- src/engine/lua.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/lua.cc b/src/engine/lua.cc index 0fac4f64..005301c4 100644 --- a/src/engine/lua.cc +++ b/src/engine/lua.cc @@ -185,7 +185,7 @@ int Lua::run(Transaction *t, const std::string &str) { lua_getglobal(L, "main"); - ms_dbg_a(t, 1, str); + ms_dbg_a(t, 9, str); /* Put the parameter on the stack. */ if (!str.empty() ) { From 5d39890783223f70548bab4359efc850ef2ead63 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Tue, 14 May 2024 01:47:59 +0000 Subject: [PATCH 49/75] Updated Transformation::evaluate signature to allow for in-place updates, removing unnecessary heap allocated copies. - Renamed Transformation::evaluate to Transformation::transform to avoid confusion with Action's overload methods. - Updated Transformation::transform signature to receive the value by reference and perform the transformation inline, if possible. - Some transformations still need to use a temporary std::string to perform their work, and then copy the result back. - Made Transformation::transform methods const and updated Transaction parameter to be const. - Transaction parameter could not be removed because it's used by just a single transformation, UrlDecodeUni. - Removed std::string Action::evaluate(const std::string &exp, Transaction *transaction); which was only implemented by Transformation but was not used from the base class, but only after downcasting to Transformation, so it can just be declared there (and not pollute other actions with a default member implementation -that does nothing- which is never called). --- headers/modsecurity/actions/action.h | 23 ++--- headers/modsecurity/rule.h | 2 +- headers/modsecurity/rule_with_actions.h | 19 ++-- src/actions/accuracy.cc | 13 +-- src/actions/action.cc | 6 -- src/actions/chain.cc | 12 +-- src/actions/maturity.cc | 13 +-- src/actions/phase.cc | 17 ++-- src/actions/rev.cc | 13 +-- src/actions/rule_id.cc | 11 +-- src/actions/transformations/base64_decode.cc | 28 ++---- src/actions/transformations/base64_decode.h | 24 ++--- .../transformations/base64_decode_ext.cc | 28 ++---- .../transformations/base64_decode_ext.h | 24 ++--- src/actions/transformations/base64_encode.cc | 28 ++---- src/actions/transformations/base64_encode.h | 24 ++--- src/actions/transformations/cmd_line.cc | 27 ++---- src/actions/transformations/cmd_line.h | 21 +---- .../transformations/compress_whitespace.cc | 29 ++---- .../transformations/compress_whitespace.h | 24 ++--- src/actions/transformations/css_decode.cc | 29 ++---- src/actions/transformations/css_decode.h | 24 ++--- .../transformations/escape_seq_decode.cc | 29 ++---- .../transformations/escape_seq_decode.h | 26 ++---- src/actions/transformations/hex_decode.cc | 28 ++---- src/actions/transformations/hex_decode.h | 24 ++--- src/actions/transformations/hex_encode.cc | 32 +++---- src/actions/transformations/hex_encode.h | 22 +---- .../transformations/html_entity_decode.cc | 30 +++---- .../transformations/html_entity_decode.h | 25 +----- src/actions/transformations/js_decode.cc | 29 ++---- src/actions/transformations/js_decode.h | 21 +---- src/actions/transformations/length.cc | 29 ++---- src/actions/transformations/length.h | 22 +---- src/actions/transformations/lower_case.cc | 24 ++--- src/actions/transformations/lower_case.h | 24 ++--- src/actions/transformations/md5.cc | 27 ++---- src/actions/transformations/md5.h | 24 ++--- src/actions/transformations/none.cc | 25 ++---- src/actions/transformations/none.h | 21 +---- src/actions/transformations/normalise_path.cc | 34 +++---- src/actions/transformations/normalise_path.h | 22 +---- .../transformations/normalise_path_win.cc | 34 +++---- .../transformations/normalise_path_win.h | 20 +---- .../transformations/parity_even_7bit.cc | 30 ++----- .../transformations/parity_even_7bit.h | 23 ++--- .../transformations/parity_odd_7bit.cc | 29 ++---- src/actions/transformations/parity_odd_7bit.h | 23 ++--- .../transformations/parity_zero_7bit.cc | 29 ++---- .../transformations/parity_zero_7bit.h | 23 ++--- .../transformations/remove_comments.cc | 28 ++---- src/actions/transformations/remove_comments.h | 26 ++---- .../transformations/remove_comments_char.cc | 23 ++--- .../transformations/remove_comments_char.h | 21 +---- src/actions/transformations/remove_nulls.cc | 24 ++--- src/actions/transformations/remove_nulls.h | 21 +---- .../transformations/remove_whitespace.cc | 23 ++--- .../transformations/remove_whitespace.h | 21 +---- .../transformations/replace_comments.cc | 31 +++---- .../transformations/replace_comments.h | 24 ++--- src/actions/transformations/replace_nulls.cc | 22 ++--- src/actions/transformations/replace_nulls.h | 24 ++--- src/actions/transformations/sha1.cc | 26 ++---- src/actions/transformations/sha1.h | 24 ++--- src/actions/transformations/sql_hex_decode.cc | 27 ++---- src/actions/transformations/sql_hex_decode.h | 24 ++--- src/actions/transformations/transformation.cc | 90 +++++++++---------- src/actions/transformations/transformation.h | 21 ++--- src/actions/transformations/trim.cc | 31 ++----- src/actions/transformations/trim.h | 30 ++----- src/actions/transformations/trim_left.cc | 32 +++---- src/actions/transformations/trim_left.h | 25 ++---- src/actions/transformations/trim_right.cc | 31 +++---- src/actions/transformations/trim_right.h | 25 ++---- src/actions/transformations/upper_case.cc | 25 ++---- src/actions/transformations/upper_case.h | 25 ++---- src/actions/transformations/url_decode.cc | 32 +++---- src/actions/transformations/url_decode.h | 26 ++---- src/actions/transformations/url_decode_uni.cc | 33 ++----- src/actions/transformations/url_decode_uni.h | 26 ++---- src/actions/transformations/url_encode.cc | 30 ++----- src/actions/transformations/url_encode.h | 26 ++---- .../transformations/utf8_to_unicode.cc | 29 ++---- src/actions/transformations/utf8_to_unicode.h | 24 ++--- src/actions/ver.cc | 13 +-- src/engine/lua.cc | 24 +++-- src/engine/lua.h | 4 +- src/modsecurity.cc | 4 +- src/operators/validate_utf8_encoding.cc | 8 ++ src/operators/validate_utf8_encoding.h | 7 -- src/rule_with_actions.cc | 61 ++++++------- src/rule_with_operator.cc | 5 +- src/utils/string.h | 20 ++--- test/coding_style_suppressions.txt | 1 - test/unit/unit.cc | 6 +- test/unit/unit_test.cc | 14 --- 96 files changed, 643 insertions(+), 1642 deletions(-) diff --git a/headers/modsecurity/actions/action.h b/headers/modsecurity/actions/action.h index 374b77d6..b1839fe7 100644 --- a/headers/modsecurity/actions/action.h +++ b/headers/modsecurity/actions/action.h @@ -13,26 +13,19 @@ * */ -#ifdef __cplusplus - -#include -#include -#include - -#endif - -#include "modsecurity/intervention.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_with_actions.h" - #ifndef HEADERS_MODSECURITY_ACTIONS_ACTION_H_ #define HEADERS_MODSECURITY_ACTIONS_ACTION_H_ #ifdef __cplusplus +#include +#include + namespace modsecurity { class Transaction; class RuleWithOperator; +class RuleWithActions; +class RuleMessage; namespace actions { @@ -74,8 +67,6 @@ class Action { virtual ~Action() { } - virtual std::string evaluate(const std::string &exp, - Transaction *transaction); virtual bool evaluate(RuleWithActions *rule, Transaction *transaction); virtual bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr ruleMessage) { @@ -87,9 +78,9 @@ class Action { void set_name_and_payload(const std::string& data) { size_t pos = data.find(":"); - std::string t = "t:"; + const char t[] = "t:"; - if (data.compare(0, t.length(), t) == 0) { + if (data.compare(0, std::size(t) - 1, t) == 0) { pos = data.find(":", 2); } diff --git a/headers/modsecurity/rule.h b/headers/modsecurity/rule.h index 1d5570a8..18e64c0a 100644 --- a/headers/modsecurity/rule.h +++ b/headers/modsecurity/rule.h @@ -52,7 +52,7 @@ namespace operators { class Operator; } -using TransformationResult = std::pair, +using TransformationResult = std::pair>; using TransformationResults = std::list; diff --git a/headers/modsecurity/rule_with_actions.h b/headers/modsecurity/rule_with_actions.h index 4b7db43f..bb63f499 100644 --- a/headers/modsecurity/rule_with_actions.h +++ b/headers/modsecurity/rule_with_actions.h @@ -119,16 +119,7 @@ class RuleWithActions : public Rule { void executeTransformations( - Transaction *trasn, const std::string &value, TransformationResults &ret); - - inline void executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, - Transaction *trans, - TransformationResults *ret, - std::string *path, - int *nth) const; - + const Transaction *trasn, const std::string &value, TransformationResults &ret); void performLogging(Transaction *trans, std::shared_ptr ruleMessage, @@ -166,6 +157,14 @@ class RuleWithActions : public Rule { RuleWithActions *m_chainedRuleParent; private: + inline void executeTransformation( + const actions::transformations::Transformation &a, + std::string &value, + const Transaction *trans, + TransformationResults *ret, + std::string *path, + int *nth) const; + /* actions */ actions::Action *m_disruptiveAction; actions::LogData *m_logData; diff --git a/src/actions/accuracy.cc b/src/actions/accuracy.cc index c8cfca72..ace9f1c5 100644 --- a/src/actions/accuracy.cc +++ b/src/actions/accuracy.cc @@ -15,16 +15,10 @@ #include "src/actions/accuracy.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Accuracy::init(std::string *error) { @@ -45,5 +39,4 @@ bool Accuracy::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/action.cc b/src/actions/action.cc index e58e2067..dd329a50 100644 --- a/src/actions/action.cc +++ b/src/actions/action.cc @@ -45,12 +45,6 @@ namespace modsecurity { namespace actions { -std::string Action::evaluate(const std::string &value, - Transaction *transaction) { - return value; -} - - bool Action::evaluate(RuleWithActions *rule, Transaction *transaction) { return true; } diff --git a/src/actions/chain.cc b/src/actions/chain.cc index 197f861f..62f0409c 100644 --- a/src/actions/chain.cc +++ b/src/actions/chain.cc @@ -15,14 +15,9 @@ #include "src/actions/chain.h" -#include -#include +#include "modsecurity/rule_with_actions.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" - -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Chain::evaluate(RuleWithActions *rule, Transaction *transaction) { @@ -31,5 +26,4 @@ bool Chain::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/maturity.cc b/src/actions/maturity.cc index 131d2148..fca6aaa4 100644 --- a/src/actions/maturity.cc +++ b/src/actions/maturity.cc @@ -15,16 +15,10 @@ #include "src/actions/maturity.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Maturity::init(std::string *error) { @@ -45,5 +39,4 @@ bool Maturity::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/phase.cc b/src/actions/phase.cc index 2e9e7277..1d17ec33 100644 --- a/src/actions/phase.cc +++ b/src/actions/phase.cc @@ -15,20 +15,15 @@ #include "src/actions/phase.h" -#include -#include - -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/modsecurity.h" +#include "modsecurity/rule_with_actions.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { + bool Phase::init(std::string *error) { - std::string a = utils::string::tolower(m_parser_payload); + const auto a = utils::string::tolower(m_parser_payload); m_phase = -1; try { @@ -77,5 +72,5 @@ bool Phase::evaluate(RuleWithActions *rule, Transaction *transaction) { return true; } -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions diff --git a/src/actions/rev.cc b/src/actions/rev.cc index 43d8d1be..6543a5da 100644 --- a/src/actions/rev.cc +++ b/src/actions/rev.cc @@ -15,16 +15,10 @@ #include "src/actions/rev.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Rev::init(std::string *error) { @@ -39,5 +33,4 @@ bool Rev::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/rule_id.cc b/src/actions/rule_id.cc index d16bf63b..c7864707 100644 --- a/src/actions/rule_id.cc +++ b/src/actions/rule_id.cc @@ -15,14 +15,10 @@ #include "src/actions/rule_id.h" -#include -#include +#include "modsecurity/rule_with_actions.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool RuleId::init(std::string *error) { @@ -54,5 +50,4 @@ bool RuleId::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/transformations/base64_decode.cc b/src/actions/transformations/base64_decode.cc index 8ddfe235..fe910e50 100644 --- a/src/actions/transformations/base64_decode.cc +++ b/src/actions/transformations/base64_decode.cc @@ -13,33 +13,19 @@ * */ -#include "src/actions/transformations/base64_decode.h" +#include "base64_decode.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Base64Decode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::decode(value); - - return ret; +bool Base64Decode::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; + value = Utils::Base64::decode(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/base64_decode.h b/src/actions/transformations/base64_decode.h index a8227699..3527bd5e 100644 --- a/src/actions/transformations/base64_decode.h +++ b/src/actions/transformations/base64_decode.h @@ -13,33 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Base64Decode : public Transformation { public: - explicit Base64Decode(const std::string &action) : Transformation(action) { } + explicit Base64Decode(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ diff --git a/src/actions/transformations/base64_decode_ext.cc b/src/actions/transformations/base64_decode_ext.cc index ee8e4b5b..e6c13987 100644 --- a/src/actions/transformations/base64_decode_ext.cc +++ b/src/actions/transformations/base64_decode_ext.cc @@ -13,33 +13,19 @@ * */ -#include "src/actions/transformations/base64_decode_ext.h" +#include "base64_decode_ext.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Base64DecodeExt::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::decode_forgiven(value); - - return ret; +bool Base64DecodeExt::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; + value = Utils::Base64::decode_forgiven(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/base64_decode_ext.h b/src/actions/transformations/base64_decode_ext.h index ad0efbdc..8f1f069e 100644 --- a/src/actions/transformations/base64_decode_ext.h +++ b/src/actions/transformations/base64_decode_ext.h @@ -13,33 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Base64DecodeExt : public Transformation { public: - explicit Base64DecodeExt(const std::string &action) : Transformation(action) { } + explicit Base64DecodeExt(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ diff --git a/src/actions/transformations/base64_encode.cc b/src/actions/transformations/base64_encode.cc index 8be74803..bf802a1e 100644 --- a/src/actions/transformations/base64_encode.cc +++ b/src/actions/transformations/base64_encode.cc @@ -13,33 +13,19 @@ * */ -#include "src/actions/transformations/base64_encode.h" +#include "base64_encode.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Base64Encode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::encode(value); - - return ret; +bool Base64Encode::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; + value = Utils::Base64::encode(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/base64_encode.h b/src/actions/transformations/base64_encode.h index 0f7fd1fe..7b3ac25e 100644 --- a/src/actions/transformations/base64_encode.h +++ b/src/actions/transformations/base64_encode.h @@ -13,33 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Base64Encode : public Transformation { public: - explicit Base64Encode(const std::string &action) : Transformation(action) { } + explicit Base64Encode(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ diff --git a/src/actions/transformations/cmd_line.cc b/src/actions/transformations/cmd_line.cc index 72087e36..cac1d2df 100644 --- a/src/actions/transformations/cmd_line.cc +++ b/src/actions/transformations/cmd_line.cc @@ -13,26 +13,13 @@ * */ -#include "src/actions/transformations/cmd_line.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "cmd_line.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string CmdLine::evaluate(const std::string &value, - Transaction *transaction) { +bool CmdLine::transform(std::string &value, const Transaction *trans) const { std::string ret; int space = 0; @@ -77,11 +64,11 @@ std::string CmdLine::evaluate(const std::string &value, } } - return ret; + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/cmd_line.h b/src/actions/transformations/cmd_line.h index 851f2938..9ba5c6b2 100644 --- a/src/actions/transformations/cmd_line.h +++ b/src/actions/transformations/cmd_line.h @@ -13,35 +13,22 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class CmdLine : public Transformation { public: explicit CmdLine(const std::string &action) : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // modsecurity::namespace actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ diff --git a/src/actions/transformations/compress_whitespace.cc b/src/actions/transformations/compress_whitespace.cc index 506de248..32c22a25 100644 --- a/src/actions/transformations/compress_whitespace.cc +++ b/src/actions/transformations/compress_whitespace.cc @@ -13,30 +13,18 @@ * */ -#include "src/actions/transformations/compress_whitespace.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "compress_whitespace.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { + CompressWhitespace::CompressWhitespace(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string CompressWhitespace::evaluate(const std::string &value, - Transaction *transaction) { +bool CompressWhitespace::transform(std::string &value, const Transaction *trans) const { std::string a; int inWhiteSpace = 0; @@ -58,9 +46,10 @@ std::string CompressWhitespace::evaluate(const std::string &value, i++; } - return a; + const auto changed = a != value; + value = a; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/compress_whitespace.h b/src/actions/transformations/compress_whitespace.h index 184ddcfa..bf90b0ba 100644 --- a/src/actions/transformations/compress_whitespace.h +++ b/src/actions/transformations/compress_whitespace.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class CompressWhitespace : public Transformation { public: + explicit CompressWhitespace(const std::string &action); - explicit CompressWhitespace(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ diff --git a/src/actions/transformations/css_decode.cc b/src/actions/transformations/css_decode.cc index f8085123..7f6938ac 100644 --- a/src/actions/transformations/css_decode.cc +++ b/src/actions/transformations/css_decode.cc @@ -13,29 +13,15 @@ * */ -#include "src/actions/transformations/css_decode.h" +#include "css_decode.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string CssDecode::evaluate(const std::string &value, - Transaction *transaction) { +bool CssDecode::transform(std::string &value, const Transaction *trans) const { char *tmp = reinterpret_cast( malloc(sizeof(char) * value.size() + 1)); @@ -47,7 +33,10 @@ std::string CssDecode::evaluate(const std::string &value, std::string ret(tmp, 0, value.size()); free(tmp); - return ret; + + const auto changed = ret != value; + value = ret; + return changed; } @@ -191,6 +180,4 @@ int CssDecode::css_decode_inplace(unsigned char *input, int64_t input_len) { } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/css_decode.h b/src/actions/transformations/css_decode.h index a6769bad..04418149 100644 --- a/src/actions/transformations/css_decode.h +++ b/src/actions/transformations/css_decode.h @@ -13,37 +13,23 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class CssDecode : public Transformation { public: explicit CssDecode(const std::string &action) : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + + bool transform(std::string &value, const Transaction *trans) const override; static int css_decode_inplace(unsigned char *input, int64_t input_len); }; - -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ diff --git a/src/actions/transformations/escape_seq_decode.cc b/src/actions/transformations/escape_seq_decode.cc index 03303272..a0dccb53 100644 --- a/src/actions/transformations/escape_seq_decode.cc +++ b/src/actions/transformations/escape_seq_decode.cc @@ -13,23 +13,12 @@ * */ -#include "src/actions/transformations/escape_seq_decode.h" +#include "escape_seq_decode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { + EscapeSeqDecode::EscapeSeqDecode(const std::string &action) : Transformation(action) { @@ -140,8 +129,7 @@ int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, } -std::string EscapeSeqDecode::evaluate(const std::string &value, - Transaction *transaction) { +bool EscapeSeqDecode::transform(std::string &value, const Transaction *trans) const { unsigned char *tmp = (unsigned char *) malloc(sizeof(char) * value.size() + 1); @@ -154,9 +142,10 @@ std::string EscapeSeqDecode::evaluate(const std::string &value, ret.assign(reinterpret_cast(tmp), size); free(tmp); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/escape_seq_decode.h b/src/actions/transformations/escape_seq_decode.h index d68f33b5..ab66464d 100644 --- a/src/actions/transformations/escape_seq_decode.h +++ b/src/actions/transformations/escape_seq_decode.h @@ -13,35 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class EscapeSeqDecode : public Transformation { public: + explicit EscapeSeqDecode(const std::string &action); - explicit EscapeSeqDecode(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); + bool transform(std::string &value, const Transaction *trans) const override; + static int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ diff --git a/src/actions/transformations/hex_decode.cc b/src/actions/transformations/hex_decode.cc index 1525377c..5866079b 100644 --- a/src/actions/transformations/hex_decode.cc +++ b/src/actions/transformations/hex_decode.cc @@ -13,27 +13,15 @@ * */ -#include "src/actions/transformations/hex_decode.h" +#include "hex_decode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { + +namespace modsecurity::actions::transformations { -std::string HexDecode::evaluate(const std::string &value, - Transaction *transaction) { +bool HexDecode::transform(std::string &value, const Transaction *trans) const { std::string ret; unsigned char *input; int size = 0; @@ -52,7 +40,9 @@ std::string HexDecode::evaluate(const std::string &value, ret.assign(reinterpret_cast(input), size); free(input); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } @@ -74,6 +64,4 @@ int HexDecode::inplace(unsigned char *data, int len) { } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/hex_decode.h b/src/actions/transformations/hex_decode.h index a2f48c6d..4239c86d 100644 --- a/src/actions/transformations/hex_decode.h +++ b/src/actions/transformations/hex_decode.h @@ -13,35 +13,23 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class HexDecode : public Transformation { public: - explicit HexDecode(const std::string &action) : Transformation(action) { } + explicit HexDecode(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static int inplace(unsigned char *data, int len); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ diff --git a/src/actions/transformations/hex_encode.cc b/src/actions/transformations/hex_encode.cc index 4e6121df..a0719726 100644 --- a/src/actions/transformations/hex_encode.cc +++ b/src/actions/transformations/hex_encode.cc @@ -13,41 +13,29 @@ * */ -#include "src/actions/transformations/hex_encode.h" +#include "hex_encode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { HexEncode::HexEncode(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string HexEncode::evaluate(const std::string &value, - Transaction *transaction) { +bool HexEncode::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; std::stringstream result; - for (std::size_t i=0; i < value.length(); i++) { - unsigned int ii = (unsigned char)(value[i]); + for (const auto c : value) { + unsigned int ii = (unsigned char)c; result << std::setw(2) << std::setfill('0') << std::hex << ii; } - return result.str(); + value = result.str(); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/hex_encode.h b/src/actions/transformations/hex_encode.h index 1ba39c56..3bb744b5 100644 --- a/src/actions/transformations/hex_encode.h +++ b/src/actions/transformations/hex_encode.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class HexEncode : public Transformation { public: - explicit HexEncode(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index 6a683245..a730f160 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -13,32 +13,21 @@ * */ -#include "src/actions/transformations/html_entity_decode.h" +#include "html_entity_decode.h" -#include +#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "src/utils/string.h" #ifdef WIN32 #include "src/compat/msvc.h" #endif -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string HtmlEntityDecode::evaluate(const std::string &value, - Transaction *transaction) { +bool HtmlEntityDecode::transform(std::string &value, const Transaction *trans) const { std::string ret; unsigned char *input; @@ -56,7 +45,9 @@ std::string HtmlEntityDecode::evaluate(const std::string &value, ret.assign(reinterpret_cast(input), i); free(input); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } @@ -207,6 +198,5 @@ HTML_ENT_OUT: return count; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/html_entity_decode.h b/src/actions/transformations/html_entity_decode.h index 44fcc323..558da5b9 100644 --- a/src/actions/transformations/html_entity_decode.h +++ b/src/actions/transformations/html_entity_decode.h @@ -13,40 +13,23 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" -#include "src/utils/string.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class HtmlEntityDecode : public Transformation { public: explicit HtmlEntityDecode(const std::string &action) : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static int inplace(unsigned char *input, uint64_t input_len); }; - -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ diff --git a/src/actions/transformations/js_decode.cc b/src/actions/transformations/js_decode.cc index 2f4cf8bb..5ed57157 100644 --- a/src/actions/transformations/js_decode.cc +++ b/src/actions/transformations/js_decode.cc @@ -13,29 +13,15 @@ * */ -#include "src/actions/transformations/js_decode.h" +#include "js_decode.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string JsDecode::evaluate(const std::string &value, - Transaction *transaction) { +bool JsDecode::transform(std::string &value, const Transaction *trans) const { std::string ret; unsigned char *input; @@ -53,7 +39,9 @@ std::string JsDecode::evaluate(const std::string &value, ret.assign(reinterpret_cast(input), i); free(input); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } @@ -163,6 +151,5 @@ int JsDecode::inplace(unsigned char *input, uint64_t input_len) { return count; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/js_decode.h b/src/actions/transformations/js_decode.h index 60d6617b..b91ab9b8 100644 --- a/src/actions/transformations/js_decode.h +++ b/src/actions/transformations/js_decode.h @@ -13,35 +13,22 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class JsDecode : public Transformation { public: explicit JsDecode(const std::string &action) : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static int inplace(unsigned char *input, uint64_t input_len); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ diff --git a/src/actions/transformations/length.cc b/src/actions/transformations/length.cc index 61015b82..10aadfe8 100644 --- a/src/actions/transformations/length.cc +++ b/src/actions/transformations/length.cc @@ -13,34 +13,21 @@ * */ -#include "src/actions/transformations/length.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "length.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { + Length::Length(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string Length::evaluate(const std::string &value, - Transaction *transaction) { - - return std::to_string(value.size()); +bool Length::transform(std::string &value, const Transaction *trans) const { + value = std::to_string(value.size()); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/length.h b/src/actions/transformations/length.h index 8892a9dc..e7b6b081 100644 --- a/src/actions/transformations/length.h +++ b/src/actions/transformations/length.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ #define SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Length : public Transformation { public: - explicit Length(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ diff --git a/src/actions/transformations/lower_case.cc b/src/actions/transformations/lower_case.cc index 7bca9479..0ea1864c 100644 --- a/src/actions/transformations/lower_case.cc +++ b/src/actions/transformations/lower_case.cc @@ -13,27 +13,20 @@ * */ -#include "src/actions/transformations/lower_case.h" -#include -#include +#include "lower_case.h" + #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { LowerCase::LowerCase(const std::string &a) : Transformation(a) { } -std::string LowerCase::evaluate(const std::string &val, - Transaction *transaction) { +bool LowerCase::transform(std::string &val, const Transaction *trans) const { std::locale loc; std::string value(val); @@ -41,9 +34,10 @@ std::string LowerCase::evaluate(const std::string &val, value[i] = std::tolower(value[i], loc); } - return value; + const auto changed = val != value; + val = value; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/lower_case.h b/src/actions/transformations/lower_case.h index 59049840..bbb51272 100644 --- a/src/actions/transformations/lower_case.h +++ b/src/actions/transformations/lower_case.h @@ -13,34 +13,20 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ -#ifdef __cplusplus - -namespace modsecurity { -class Transaction; -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class LowerCase : public Transformation { public: explicit LowerCase(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ diff --git a/src/actions/transformations/md5.cc b/src/actions/transformations/md5.cc index 71c36bc3..b1cdc93e 100644 --- a/src/actions/transformations/md5.cc +++ b/src/actions/transformations/md5.cc @@ -13,32 +13,17 @@ * */ -#include "src/actions/transformations/md5.h" +#include "md5.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/md5.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Md5::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Md5::digest(value); - - return ret; +bool Md5::transform(std::string &value, const Transaction *trans) const { + value = Utils::Md5::digest(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/md5.h b/src/actions/transformations/md5.h index 37f22473..9d5a15f8 100644 --- a/src/actions/transformations/md5.h +++ b/src/actions/transformations/md5.h @@ -13,33 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ #define SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Md5 : public Transformation { public: - explicit Md5(const std::string &action) : Transformation(action) { } + explicit Md5(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ diff --git a/src/actions/transformations/none.cc b/src/actions/transformations/none.cc index f122bf03..adbf32a6 100644 --- a/src/actions/transformations/none.cc +++ b/src/actions/transformations/none.cc @@ -13,30 +13,15 @@ * */ -#include "src/actions/transformations/none.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "none.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string None::evaluate(const std::string &value, - Transaction *transaction) { - return value; +bool None::transform(std::string &value, const Transaction *trans) const { + return false; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/none.h b/src/actions/transformations/none.h index e8a0e9d9..2fe428bb 100644 --- a/src/actions/transformations/none.h +++ b/src/actions/transformations/none.h @@ -13,20 +13,12 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class None : public Transformation { public: @@ -34,14 +26,9 @@ class None : public Transformation { : Transformation(action) { m_isNone = true; } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ diff --git a/src/actions/transformations/normalise_path.cc b/src/actions/transformations/normalise_path.cc index e75b9849..c663b98a 100644 --- a/src/actions/transformations/normalise_path.cc +++ b/src/actions/transformations/normalise_path.cc @@ -13,33 +13,19 @@ * */ -#include "src/actions/transformations/normalise_path.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "normalise_path.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { + NormalisePath::NormalisePath(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string NormalisePath::evaluate(const std::string &value, - Transaction *transaction) { - int changed = 0; +bool NormalisePath::transform(std::string &value, const Transaction *trans) const { + int _changed = 0; char *tmp = reinterpret_cast( malloc(sizeof(char) * value.size() + 1)); @@ -47,13 +33,15 @@ std::string NormalisePath::evaluate(const std::string &value, tmp[value.size()] = '\0'; int i = normalize_path_inplace((unsigned char *)tmp, - value.size(), 0, &changed); + value.size(), 0, &_changed); std::string ret(""); ret.assign(tmp, i); free(tmp); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } @@ -223,6 +211,4 @@ length: } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/normalise_path.h b/src/actions/transformations/normalise_path.h index b3869bea..d5b84085 100644 --- a/src/actions/transformations/normalise_path.h +++ b/src/actions/transformations/normalise_path.h @@ -13,37 +13,23 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class NormalisePath : public Transformation { public: - explicit NormalisePath(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static int normalize_path_inplace(unsigned char *input, int input_len, int win, int *changed); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ diff --git a/src/actions/transformations/normalise_path_win.cc b/src/actions/transformations/normalise_path_win.cc index 6c171a59..49f6989f 100644 --- a/src/actions/transformations/normalise_path_win.cc +++ b/src/actions/transformations/normalise_path_win.cc @@ -13,30 +13,16 @@ * */ -#include "src/actions/transformations/normalise_path_win.h" +#include "normalise_path_win.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/normalise_path.h" +#include "normalise_path.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string NormalisePathWin::evaluate(const std::string &value, - Transaction *transaction) { - int changed; +bool NormalisePathWin::transform(std::string &value, const Transaction *trans) const { + int _changed; char *tmp = reinterpret_cast( malloc(sizeof(char) * value.size() + 1)); @@ -45,16 +31,16 @@ std::string NormalisePathWin::evaluate(const std::string &value, int i = NormalisePath::normalize_path_inplace( reinterpret_cast(tmp), - value.size(), 1, &changed); + value.size(), 1, &_changed); std::string ret(""); ret.assign(tmp, i); free(tmp); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/normalise_path_win.h b/src/actions/transformations/normalise_path_win.h index a1f8c5f7..af312693 100644 --- a/src/actions/transformations/normalise_path_win.h +++ b/src/actions/transformations/normalise_path_win.h @@ -13,33 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ +#include "transformation.h" -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class NormalisePathWin : public Transformation { public: explicit NormalisePathWin(const std::string &action) : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ diff --git a/src/actions/transformations/parity_even_7bit.cc b/src/actions/transformations/parity_even_7bit.cc index 2c0be31c..f2992240 100644 --- a/src/actions/transformations/parity_even_7bit.cc +++ b/src/actions/transformations/parity_even_7bit.cc @@ -13,28 +13,17 @@ * */ -#include "src/actions/transformations/parity_even_7bit.h" +#include "parity_even_7bit.h" -#include -#include -#include -#include -#include -#include #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + +namespace modsecurity::actions::transformations { -namespace modsecurity { -namespace actions { -namespace transformations { +bool ParityEven7bit::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; - -std::string ParityEven7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; unsigned char *input; input = reinterpret_cast @@ -46,9 +35,9 @@ std::string ParityEven7bit::evaluate(const std::string &value, std::memcpy(input, value.c_str(), value.length()+1); - inplace(input, value.length()); + const auto ret = inplace(input, value.length()); - ret.assign(reinterpret_cast(input), value.length()); + value.assign(reinterpret_cast(input), value.length()); free(input); return ret; @@ -76,7 +65,4 @@ bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) { } - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_even_7bit.h b/src/actions/transformations/parity_even_7bit.h index 08aa8823..41010d62 100644 --- a/src/actions/transformations/parity_even_7bit.h +++ b/src/actions/transformations/parity_even_7bit.h @@ -13,33 +13,22 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ParityEven7bit : public Transformation { public: - explicit ParityEven7bit(const std::string &action) : Transformation(action) { } + explicit ParityEven7bit(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static bool inplace(unsigned char *input, uint64_t input_len); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ diff --git a/src/actions/transformations/parity_odd_7bit.cc b/src/actions/transformations/parity_odd_7bit.cc index 5ac38d20..f8192ef3 100644 --- a/src/actions/transformations/parity_odd_7bit.cc +++ b/src/actions/transformations/parity_odd_7bit.cc @@ -13,28 +13,17 @@ * */ -#include "src/actions/transformations/parity_odd_7bit.h" +#include "parity_odd_7bit.h" -#include -#include -#include -#include -#include -#include #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + +namespace modsecurity::actions::transformations { -namespace modsecurity { -namespace actions { -namespace transformations { +bool ParityOdd7bit::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; - -std::string ParityOdd7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; unsigned char *input; input = reinterpret_cast @@ -46,9 +35,9 @@ std::string ParityOdd7bit::evaluate(const std::string &value, memcpy(input, value.c_str(), value.length()+1); - inplace(input, value.length()); + const auto ret = inplace(input, value.length()); - ret.assign(reinterpret_cast(input), value.length()); + value.assign(reinterpret_cast(input), value.length()); free(input); return ret; @@ -76,6 +65,4 @@ bool ParityOdd7bit::inplace(unsigned char *input, uint64_t input_len) { } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_odd_7bit.h b/src/actions/transformations/parity_odd_7bit.h index 8b7e34d2..1afa1327 100644 --- a/src/actions/transformations/parity_odd_7bit.h +++ b/src/actions/transformations/parity_odd_7bit.h @@ -13,33 +13,22 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ParityOdd7bit : public Transformation { public: - explicit ParityOdd7bit(const std::string &action) : Transformation(action) { } + explicit ParityOdd7bit(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static bool inplace(unsigned char *input, uint64_t input_len); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ diff --git a/src/actions/transformations/parity_zero_7bit.cc b/src/actions/transformations/parity_zero_7bit.cc index 7bb84636..ef80b74d 100644 --- a/src/actions/transformations/parity_zero_7bit.cc +++ b/src/actions/transformations/parity_zero_7bit.cc @@ -13,28 +13,17 @@ * */ -#include "src/actions/transformations/parity_zero_7bit.h" +#include "parity_zero_7bit.h" -#include -#include -#include -#include -#include -#include #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + +namespace modsecurity::actions::transformations { -namespace modsecurity { -namespace actions { -namespace transformations { +bool ParityZero7bit::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; - -std::string ParityZero7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; unsigned char *input; input = reinterpret_cast @@ -46,9 +35,9 @@ std::string ParityZero7bit::evaluate(const std::string &value, memcpy(input, value.c_str(), value.length()+1); - inplace(input, value.length()); + const auto ret = inplace(input, value.length()); - ret.assign(reinterpret_cast(input), value.length()); + value.assign(reinterpret_cast(input), value.length()); free(input); return ret; @@ -68,6 +57,4 @@ bool ParityZero7bit::inplace(unsigned char *input, uint64_t input_len) { } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_zero_7bit.h b/src/actions/transformations/parity_zero_7bit.h index 4b4ccd23..af47f7c5 100644 --- a/src/actions/transformations/parity_zero_7bit.h +++ b/src/actions/transformations/parity_zero_7bit.h @@ -13,33 +13,22 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ParityZero7bit : public Transformation { public: - explicit ParityZero7bit(const std::string &action) : Transformation(action) { } + explicit ParityZero7bit(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static bool inplace(unsigned char *input, uint64_t input_len); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ diff --git a/src/actions/transformations/remove_comments.cc b/src/actions/transformations/remove_comments.cc index 043dd950..1515675c 100644 --- a/src/actions/transformations/remove_comments.cc +++ b/src/actions/transformations/remove_comments.cc @@ -13,27 +13,13 @@ * */ -#include "src/actions/transformations/remove_comments.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "remove_comments.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string RemoveComments::evaluate(const std::string &value, - Transaction *transaction) { +bool RemoveComments::transform(std::string &value, const Transaction *trans) const { std::string ret; unsigned char *input; @@ -103,10 +89,10 @@ std::string RemoveComments::evaluate(const std::string &value, ret.assign(reinterpret_cast(input), j); free(input); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_comments.h b/src/actions/transformations/remove_comments.h index 78dd213d..67f0ff5b 100644 --- a/src/actions/transformations/remove_comments.h +++ b/src/actions/transformations/remove_comments.h @@ -13,35 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class RemoveComments : public Transformation { public: - explicit RemoveComments(const std::string &action) : Transformation(action) { } + explicit RemoveComments(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; - -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ diff --git a/src/actions/transformations/remove_comments_char.cc b/src/actions/transformations/remove_comments_char.cc index 4c54e68a..7a4763d3 100644 --- a/src/actions/transformations/remove_comments_char.cc +++ b/src/actions/transformations/remove_comments_char.cc @@ -13,25 +13,17 @@ * */ -#include "src/actions/transformations/remove_comments_char.h" - -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "remove_comments_char.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { RemoveCommentsChar::RemoveCommentsChar(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string RemoveCommentsChar::evaluate(const std::string &val, - Transaction *transaction) { +bool RemoveCommentsChar::transform(std::string &val, const Transaction *trans) const { size_t i = 0; std::string transformed_value; transformed_value.reserve(val.size()); @@ -65,10 +57,11 @@ std::string RemoveCommentsChar::evaluate(const std::string &val, i++; } } - return transformed_value; + + const auto changed = transformed_value != val; + val = transformed_value; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_comments_char.h b/src/actions/transformations/remove_comments_char.h index 722aba59..2066fd65 100644 --- a/src/actions/transformations/remove_comments_char.h +++ b/src/actions/transformations/remove_comments_char.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class RemoveCommentsChar : public Transformation { public: explicit RemoveCommentsChar(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ diff --git a/src/actions/transformations/remove_nulls.cc b/src/actions/transformations/remove_nulls.cc index 2d479c73..bda34bbe 100644 --- a/src/actions/transformations/remove_nulls.cc +++ b/src/actions/transformations/remove_nulls.cc @@ -13,23 +13,13 @@ * */ -#include "src/actions/transformations/remove_nulls.h" - -#include - -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "remove_nulls.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string RemoveNulls::evaluate(const std::string &val, - Transaction *transaction) { +bool RemoveNulls::transform(std::string &val, const Transaction *trans) const { size_t i = 0; std::string transformed_value; transformed_value.reserve(val.size()); @@ -43,10 +33,10 @@ std::string RemoveNulls::evaluate(const std::string &val, i++; } - return transformed_value; + const auto changed = transformed_value != val; + val = transformed_value; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_nulls.h b/src/actions/transformations/remove_nulls.h index eeb33b36..56df24c8 100644 --- a/src/actions/transformations/remove_nulls.h +++ b/src/actions/transformations/remove_nulls.h @@ -13,34 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class RemoveNulls : public Transformation { public: explicit RemoveNulls(const std::string &action) : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ diff --git a/src/actions/transformations/remove_whitespace.cc b/src/actions/transformations/remove_whitespace.cc index 37964663..8cee80c9 100644 --- a/src/actions/transformations/remove_whitespace.cc +++ b/src/actions/transformations/remove_whitespace.cc @@ -13,25 +13,17 @@ * */ -#include "src/actions/transformations/remove_whitespace.h" +#include "remove_whitespace.h" -#include +namespace modsecurity::actions::transformations { -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" - - -namespace modsecurity { -namespace actions { -namespace transformations { RemoveWhitespace::RemoveWhitespace(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string RemoveWhitespace::evaluate(const std::string &val, - Transaction *transaction) { +bool RemoveWhitespace::transform(std::string &val, const Transaction *trans) const { std::string transformed_value; transformed_value.reserve(val.size()); @@ -52,10 +44,11 @@ std::string RemoveWhitespace::evaluate(const std::string &val, i++; } - return transformed_value; + const auto changed = transformed_value != val; + val = transformed_value; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_whitespace.h b/src/actions/transformations/remove_whitespace.h index f977914c..a9925f8e 100644 --- a/src/actions/transformations/remove_whitespace.h +++ b/src/actions/transformations/remove_whitespace.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class RemoveWhitespace : public Transformation { public: explicit RemoveWhitespace(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ diff --git a/src/actions/transformations/replace_comments.cc b/src/actions/transformations/replace_comments.cc index 77e3e3b7..b1aeecf9 100644 --- a/src/actions/transformations/replace_comments.cc +++ b/src/actions/transformations/replace_comments.cc @@ -13,31 +13,19 @@ * */ -#include "src/actions/transformations/replace_comments.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "replace_comments.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { + ReplaceComments::ReplaceComments(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string ReplaceComments::evaluate(const std::string &value, - Transaction *transaction) { + +bool ReplaceComments::transform(std::string &value, const Transaction *trans) const { uint64_t i, j, incomment; char *input = reinterpret_cast( @@ -80,9 +68,10 @@ std::string ReplaceComments::evaluate(const std::string &value, free(input); - return resp; + const auto changed = resp != value; + value = resp; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/replace_comments.h b/src/actions/transformations/replace_comments.h index 6808f426..95e5e854 100644 --- a/src/actions/transformations/replace_comments.h +++ b/src/actions/transformations/replace_comments.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ReplaceComments : public Transformation { public: + explicit ReplaceComments(const std::string &action); - explicit ReplaceComments(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ diff --git a/src/actions/transformations/replace_nulls.cc b/src/actions/transformations/replace_nulls.cc index 1af860f4..c59ceb87 100644 --- a/src/actions/transformations/replace_nulls.cc +++ b/src/actions/transformations/replace_nulls.cc @@ -13,25 +13,17 @@ * */ -#include "src/actions/transformations/replace_nulls.h" - -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "replace_nulls.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { ReplaceNulls::ReplaceNulls(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string ReplaceNulls::evaluate(const std::string &val, - Transaction *transaction) { +bool ReplaceNulls::transform(std::string &val, const Transaction *trans) const { int64_t i; std::string value(val); @@ -44,9 +36,9 @@ std::string ReplaceNulls::evaluate(const std::string &val, } } - return value; + const auto changed = val != value; + val = value; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/replace_nulls.h b/src/actions/transformations/replace_nulls.h index 8e2d315f..ad206ae4 100644 --- a/src/actions/transformations/replace_nulls.h +++ b/src/actions/transformations/replace_nulls.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ReplaceNulls : public Transformation { public: + explicit ReplaceNulls(const std::string &action); - explicit ReplaceNulls(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ diff --git a/src/actions/transformations/sha1.cc b/src/actions/transformations/sha1.cc index 9e0c7f53..af1eda41 100644 --- a/src/actions/transformations/sha1.cc +++ b/src/actions/transformations/sha1.cc @@ -13,35 +13,21 @@ * */ -#include "src/actions/transformations/sha1.h" +#include "sha1.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/sha1.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { Sha1::Sha1(const std::string &action) : Transformation(action) { this->action_kind = 1; } -std::string Sha1::evaluate(const std::string &value, - Transaction *transaction) { - - return Utils::Sha1::digest(value); +bool Sha1::transform(std::string &value, const Transaction *trans) const { + value = Utils::Sha1::digest(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/sha1.h b/src/actions/transformations/sha1.h index eb5fb3f1..263ed978 100644 --- a/src/actions/transformations/sha1.h +++ b/src/actions/transformations/sha1.h @@ -13,32 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ #define SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Sha1 : public Transformation { public: - explicit Sha1(const std::string &action) ; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + explicit Sha1(const std::string &action); + + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ diff --git a/src/actions/transformations/sql_hex_decode.cc b/src/actions/transformations/sql_hex_decode.cc index 8c8805ff..41189f92 100644 --- a/src/actions/transformations/sql_hex_decode.cc +++ b/src/actions/transformations/sql_hex_decode.cc @@ -13,24 +13,15 @@ * */ -#include "src/actions/transformations/sql_hex_decode.h" +#include "sql_hex_decode.h" -#include -#include -#include -#include -#include -#include #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { + #ifndef VALID_HEX #define VALID_HEX(X) (((X >= '0') && (X <= '9')) \ @@ -41,8 +32,7 @@ namespace transformations { #define ISODIGIT(X) ((X >= '0') && (X <= '7')) #endif -std::string SqlHexDecode::evaluate(const std::string &value, - Transaction *transaction) { +bool SqlHexDecode::transform(std::string &value, const Transaction *trans) const { std::string ret; unsigned char *input; int size = 0; @@ -61,7 +51,9 @@ std::string SqlHexDecode::evaluate(const std::string &value, ret.assign(reinterpret_cast(input), size); free(input); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } @@ -107,7 +99,4 @@ int SqlHexDecode::inplace(unsigned char *data, int len) { } - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/sql_hex_decode.h b/src/actions/transformations/sql_hex_decode.h index 9a3afe0f..a92a0a2b 100644 --- a/src/actions/transformations/sql_hex_decode.h +++ b/src/actions/transformations/sql_hex_decode.h @@ -13,27 +13,19 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class SqlHexDecode : public Transformation { public: - explicit SqlHexDecode(const std::string &action) : Transformation(action) { } + explicit SqlHexDecode(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static int inplace(unsigned char *data, int len); @@ -45,10 +37,6 @@ class SqlHexDecode : public Transformation { } }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ diff --git a/src/actions/transformations/transformation.cc b/src/actions/transformations/transformation.cc index 3b38431a..b6fbf5a3 100644 --- a/src/actions/transformations/transformation.cc +++ b/src/actions/transformations/transformation.cc @@ -13,65 +13,62 @@ * */ -#include "src/actions/transformations/transformation.h" +#include "transformation.h" #include - #include #include #include "modsecurity/transaction.h" #include "modsecurity/actions/action.h" -#include "src/actions/transformations/base64_decode_ext.h" -#include "src/actions/transformations/base64_decode.h" -#include "src/actions/transformations/base64_encode.h" -#include "src/actions/transformations/cmd_line.h" -#include "src/actions/transformations/compress_whitespace.h" -#include "src/actions/transformations/css_decode.h" -#include "src/actions/transformations/escape_seq_decode.h" -#include "src/actions/transformations/hex_decode.h" -#include "src/actions/transformations/hex_encode.h" -#include "src/actions/transformations/html_entity_decode.h" -#include "src/actions/transformations/js_decode.h" -#include "src/actions/transformations/length.h" -#include "src/actions/transformations/lower_case.h" -#include "src/actions/transformations/md5.h" -#include "src/actions/transformations/none.h" -#include "src/actions/transformations/normalise_path.h" -#include "src/actions/transformations/normalise_path_win.h" -#include "src/actions/transformations/parity_even_7bit.h" -#include "src/actions/transformations/parity_odd_7bit.h" -#include "src/actions/transformations/parity_zero_7bit.h" -#include "src/actions/transformations/remove_comments_char.h" -#include "src/actions/transformations/remove_comments.h" -#include "src/actions/transformations/remove_nulls.h" -#include "src/actions/transformations/remove_whitespace.h" -#include "src/actions/transformations/replace_comments.h" -#include "src/actions/transformations/replace_nulls.h" -#include "src/actions/transformations/sha1.h" -#include "src/actions/transformations/sql_hex_decode.h" -#include "src/actions/transformations/trim.h" -#include "src/actions/transformations/trim_left.h" -#include "src/actions/transformations/trim_right.h" -#include "src/actions/transformations/upper_case.h" -#include "src/actions/transformations/url_decode.h" -#include "src/actions/transformations/url_decode_uni.h" -#include "src/actions/transformations/url_encode.h" -#include "src/actions/transformations/utf8_to_unicode.h" + +#include "base64_decode_ext.h" +#include "base64_decode.h" +#include "base64_encode.h" +#include "cmd_line.h" +#include "compress_whitespace.h" +#include "css_decode.h" +#include "escape_seq_decode.h" +#include "hex_decode.h" +#include "hex_encode.h" +#include "html_entity_decode.h" +#include "js_decode.h" +#include "length.h" +#include "lower_case.h" +#include "md5.h" +#include "none.h" +#include "normalise_path.h" +#include "normalise_path_win.h" +#include "parity_even_7bit.h" +#include "parity_odd_7bit.h" +#include "parity_zero_7bit.h" +#include "remove_comments_char.h" +#include "remove_comments.h" +#include "remove_nulls.h" +#include "remove_whitespace.h" +#include "replace_comments.h" +#include "replace_nulls.h" +#include "sha1.h" +#include "sql_hex_decode.h" +#include "trim.h" +#include "trim_left.h" +#include "trim_right.h" +#include "upper_case.h" +#include "url_decode.h" +#include "url_decode_uni.h" +#include "url_encode.h" +#include "utf8_to_unicode.h" #define IF_MATCH(b) \ if (a.compare(2, std::strlen(#b), #b) == 0) -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Transformation::evaluate(const std::string &value, - Transaction *transaction) { - return value; +bool Transformation::transform(std::string &value, const Transaction *trans) const { + return false; } Transformation* Transformation::instantiate(std::string a) { @@ -119,6 +116,5 @@ Transformation* Transformation::instantiate(std::string a) { return new Transformation(a); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/transformation.h b/src/actions/transformations/transformation.h index f1d81503..3677dcef 100644 --- a/src/actions/transformations/transformation.h +++ b/src/actions/transformations/transformation.h @@ -13,19 +13,12 @@ * */ -#include - -#include "modsecurity/actions/action.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ +#include "modsecurity/actions/action.h" -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Transformation : public Action { public: @@ -35,15 +28,11 @@ class Transformation : public Action { explicit Transformation(const std::string& _action, int kind) : Action(_action, kind) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - static Transformation* instantiate(std::string a); + + virtual bool transform(std::string &value, const Transaction *trans) const; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ diff --git a/src/actions/transformations/trim.cc b/src/actions/transformations/trim.cc index 5902497f..a5515346 100644 --- a/src/actions/transformations/trim.cc +++ b/src/actions/transformations/trim.cc @@ -13,22 +13,10 @@ * */ -#include "src/actions/transformations/trim.h" +#include "trim.h" -#include -#include -#include -#include -#include -#include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { std::string *Trim::ltrim(std::string *s) { @@ -66,14 +54,13 @@ Trim::Trim(const std::string &action) } -std::string -Trim::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *this->trim(&value); +bool Trim::transform(std::string &value, const Transaction *trans) const { + std::string ret(value); + this->trim(&ret); + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/trim.h b/src/actions/transformations/trim.h index ac16050c..3b0e82d9 100644 --- a/src/actions/transformations/trim.h +++ b/src/actions/transformations/trim.h @@ -13,38 +13,24 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Trim : public Transformation { public: + explicit Trim(const std::string &action); - explicit Trim(const std::string &action) ; + bool transform(std::string &value, const Transaction *trans) const override; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - std::string *ltrim(std::string *s); - std::string *rtrim(std::string *s); - std::string *trim(std::string *s); + static std::string *ltrim(std::string *s); + static std::string *rtrim(std::string *s); + static std::string *trim(std::string *s); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ diff --git a/src/actions/transformations/trim_left.cc b/src/actions/transformations/trim_left.cc index 50c0cc6a..c141727a 100644 --- a/src/actions/transformations/trim_left.cc +++ b/src/actions/transformations/trim_left.cc @@ -13,23 +13,10 @@ * */ -#include "src/actions/transformations/trim_left.h" +#include "trim_left.h" -#include -#include -#include -#include -#include -#include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/trim.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { @@ -38,12 +25,13 @@ TrimLeft::TrimLeft(const std::string &action) this->action_kind = 1; } -std::string TrimLeft::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *ltrim(&value); +bool TrimLeft::transform(std::string &value, const Transaction *trans) const { + std::string ret(value); + this->ltrim(&ret); + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/trim_left.h b/src/actions/transformations/trim_left.h index 54e4885c..5d5a0a57 100644 --- a/src/actions/transformations/trim_left.h +++ b/src/actions/transformations/trim_left.h @@ -13,34 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/trim.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" +#include "trim.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class TrimLeft : public Trim { public: - explicit TrimLeft(const std::string &action) ; + explicit TrimLeft(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ diff --git a/src/actions/transformations/trim_right.cc b/src/actions/transformations/trim_right.cc index 92383f7e..b95b63aa 100644 --- a/src/actions/transformations/trim_right.cc +++ b/src/actions/transformations/trim_right.cc @@ -13,22 +13,10 @@ * */ -#include "src/actions/transformations/trim_right.h" +#include "trim_right.h" -#include -#include -#include -#include -#include -#include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { TrimRight::TrimRight(const std::string &action) @@ -36,12 +24,13 @@ TrimRight::TrimRight(const std::string &action) this->action_kind = 1; } -std::string TrimRight::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *this->rtrim(&value); +bool TrimRight::transform(std::string &value, const Transaction *trans) const { + std::string ret(value); + this->rtrim(&ret); + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/trim_right.h b/src/actions/transformations/trim_right.h index 9a96b4c5..eb13fb20 100644 --- a/src/actions/transformations/trim_right.h +++ b/src/actions/transformations/trim_right.h @@ -13,34 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/trim.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" +#include "trim.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class TrimRight : public Trim { public: - explicit TrimRight(const std::string &action) ; + explicit TrimRight(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ diff --git a/src/actions/transformations/upper_case.cc b/src/actions/transformations/upper_case.cc index 998ec725..2b8ad1d9 100644 --- a/src/actions/transformations/upper_case.cc +++ b/src/actions/transformations/upper_case.cc @@ -13,27 +13,19 @@ * */ -#include "src/actions/transformations/upper_case.h" -#include -#include +#include "upper_case.h" + #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { UpperCase::UpperCase(const std::string &a) : Transformation(a) { } -std::string UpperCase::evaluate(const std::string &val, - Transaction *transaction) { +bool UpperCase::transform(std::string &val, const Transaction *trans) const { std::string value(val); std::locale loc; @@ -41,9 +33,10 @@ std::string UpperCase::evaluate(const std::string &val, value[i] = std::toupper(value[i], loc); } - return value; + const auto changed = val != value; + val = value; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/upper_case.h b/src/actions/transformations/upper_case.h index f4a77220..70c806b0 100644 --- a/src/actions/transformations/upper_case.h +++ b/src/actions/transformations/upper_case.h @@ -13,35 +13,20 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ -#ifdef __cplusplus - -namespace modsecurity { -class Transaction; -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class UpperCase : public Transformation { public: - explicit UpperCase(const std::string &action) ; + explicit UpperCase(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index 845c6a64..7e5f8767 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -13,23 +13,12 @@ * */ -#include "src/actions/transformations/url_decode.h" +#include "url_decode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/decode.h" -namespace modsecurity { -namespace actions { -namespace transformations { + +namespace modsecurity::actions::transformations { UrlDecode::UrlDecode(const std::string &action) @@ -37,28 +26,27 @@ UrlDecode::UrlDecode(const std::string &action) this->action_kind = 1; } -std::string UrlDecode::evaluate(const std::string &value, - Transaction *transaction) { +bool UrlDecode::transform(std::string &value, const Transaction *trans) const { unsigned char *val(NULL); int invalid_count = 0; - int changed; + int _changed; val = (unsigned char *) malloc(sizeof(char) * value.size() + 1); memcpy(val, value.c_str(), value.size() + 1); val[value.size()] = '\0'; int size = utils::urldecode_nonstrict_inplace(val, value.size(), - &invalid_count, &changed); + &invalid_count, &_changed); std::string out; out.append((const char *)val, size); free(val); - return out; + const auto changed = out != value; + value = out; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_decode.h b/src/actions/transformations/url_decode.h index e965dae7..5c5c2662 100644 --- a/src/actions/transformations/url_decode.h +++ b/src/actions/transformations/url_decode.h @@ -13,36 +13,20 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class UrlDecode : public Transformation { public: + explicit UrlDecode(const std::string &action); - explicit UrlDecode(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ diff --git a/src/actions/transformations/url_decode_uni.cc b/src/actions/transformations/url_decode_uni.cc index ad5b8111..fdc2e79b 100644 --- a/src/actions/transformations/url_decode_uni.cc +++ b/src/actions/transformations/url_decode_uni.cc @@ -13,33 +13,16 @@ * */ -#include "src/actions/transformations/url_decode_uni.h" +#include "url_decode_uni.h" -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/rules_set_properties.h" #include "modsecurity/rules_set.h" -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -#include "src/utils/system.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string UrlDecodeUni::evaluate(const std::string &value, - Transaction *t) { +bool UrlDecodeUni::transform(std::string &value, const Transaction *t) const { std::string ret; unsigned char *input; @@ -57,7 +40,9 @@ std::string UrlDecodeUni::evaluate(const std::string &value, ret.assign(reinterpret_cast(input), i); free(input); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } @@ -66,7 +51,7 @@ std::string UrlDecodeUni::evaluate(const std::string &value, * IMP1 Assumes NUL-terminated */ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, - Transaction *t) { + const Transaction *t) { unsigned char *d = input; int64_t i, count, fact, j, xv; int Code, hmap = -1; @@ -190,6 +175,4 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_decode_uni.h b/src/actions/transformations/url_decode_uni.h index d7b0dd21..31962851 100644 --- a/src/actions/transformations/url_decode_uni.h +++ b/src/actions/transformations/url_decode_uni.h @@ -13,35 +13,23 @@ * */ -#include - -#include "modsecurity/rules_set_properties.h" -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ +#include "transformation.h" -#ifdef __cplusplus -namespace modsecurity { -class Transaction; -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class UrlDecodeUni : public Transformation { public: - explicit UrlDecodeUni(const std::string &action) : Transformation(action) { } + explicit UrlDecodeUni(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static int inplace(unsigned char *input, uint64_t input_len, - Transaction *transaction); + const Transaction *transaction); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ diff --git a/src/actions/transformations/url_encode.cc b/src/actions/transformations/url_encode.cc index 056755ca..e7f59f85 100644 --- a/src/actions/transformations/url_encode.cc +++ b/src/actions/transformations/url_encode.cc @@ -13,22 +13,11 @@ * */ -#include "src/actions/transformations/url_encode.h" +#include "url_encode.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { UrlEncode::UrlEncode(const std::string &action) @@ -87,16 +76,15 @@ std::string UrlEncode::url_enc(const char *input, } -std::string UrlEncode::evaluate(const std::string &value, - Transaction *transaction) { - int changed; +bool UrlEncode::transform(std::string &value, const Transaction *trans) const { + int _changed; - std::string ret = url_enc(value.c_str(), value.size(), &changed); + std::string ret = url_enc(value.c_str(), value.size(), &_changed); - return ret; + const auto changed = ret != value; + value = ret; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_encode.h b/src/actions/transformations/url_encode.h index a45be564..b300c40d 100644 --- a/src/actions/transformations/url_encode.h +++ b/src/actions/transformations/url_encode.h @@ -13,37 +13,23 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class UrlEncode : public Transformation { public: + explicit UrlEncode(const std::string &action); - explicit UrlEncode(const std::string &action) ; + bool transform(std::string &value, const Transaction *trans) const override; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - std::string url_enc(const char *input, + static std::string url_enc(const char *input, unsigned int input_len, int *changed); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ diff --git a/src/actions/transformations/utf8_to_unicode.cc b/src/actions/transformations/utf8_to_unicode.cc index 70c1f9c8..2f40ce60 100644 --- a/src/actions/transformations/utf8_to_unicode.cc +++ b/src/actions/transformations/utf8_to_unicode.cc @@ -13,31 +13,20 @@ * */ -#include "src/actions/transformations/utf8_to_unicode.h" +#include "utf8_to_unicode.h" -#include -#include -#include -#include -#include -#include #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Utf8ToUnicode::evaluate(const std::string &value, - Transaction *transaction) { +bool Utf8ToUnicode::transform(std::string &value, const Transaction *trans) const { std::string ret; unsigned char *input; - int changed = 0; + int _changed = 0; char *out; input = reinterpret_cast @@ -49,7 +38,7 @@ std::string Utf8ToUnicode::evaluate(const std::string &value, memcpy(input, value.c_str(), value.length()+1); - out = inplace(input, value.size() + 1, &changed); + out = inplace(input, value.size() + 1, &_changed); free(input); if (out != NULL) { ret.assign(reinterpret_cast(out), @@ -57,7 +46,9 @@ std::string Utf8ToUnicode::evaluate(const std::string &value, free(out); } - return ret; + const auto changed = ret != value; + value = ret; + return changed; } @@ -313,6 +304,4 @@ char *Utf8ToUnicode::inplace(unsigned char *input, } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/utf8_to_unicode.h b/src/actions/transformations/utf8_to_unicode.h index 4d488410..83aba819 100644 --- a/src/actions/transformations/utf8_to_unicode.h +++ b/src/actions/transformations/utf8_to_unicode.h @@ -13,40 +13,30 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ +#include "transformation.h" + #define UNICODE_ERROR_CHARACTERS_MISSING -1 #define UNICODE_ERROR_INVALID_ENCODING -2 #define UNICODE_ERROR_OVERLONG_CHARACTER -3 #define UNICODE_ERROR_RESTRICTED_CHARACTER -4 #define UNICODE_ERROR_DECODING_ERROR -5 -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Utf8ToUnicode : public Transformation { public: - explicit Utf8ToUnicode(const std::string &action) : Transformation(action) { } + explicit Utf8ToUnicode(const std::string &action) + : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; static char *inplace(unsigned char *input, uint64_t input_len, int *changed); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ diff --git a/src/actions/ver.cc b/src/actions/ver.cc index 43b8b832..d7b8bdc4 100644 --- a/src/actions/ver.cc +++ b/src/actions/ver.cc @@ -15,16 +15,10 @@ #include "src/actions/ver.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Ver::evaluate(RuleWithActions *rule, Transaction *transaction) { @@ -33,5 +27,4 @@ bool Ver::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/engine/lua.cc b/src/engine/lua.cc index 0fac4f64..01a3eace 100644 --- a/src/engine/lua.cc +++ b/src/engine/lua.cc @@ -267,7 +267,7 @@ int Lua::getvar(lua_State *L) { t = reinterpret_cast(z); std::string var = variables::Variable::stringMatchResolve(t, varname); - var = applyTransformations(L, t, 2, var); + applyTransformations(L, t, 2, var); if (var.size() == 0) { lua_pushnil(L); @@ -407,12 +407,10 @@ int Lua::setvar(lua_State *L) { } -std::string Lua::applyTransformations(lua_State *L, Transaction *t, - int idx, std::string var) { - std::string newVar = var; - +void Lua::applyTransformations(lua_State *L, const Transaction *t, + int idx, std::string &var) { if (lua_isuserdata(L, idx) || lua_isnoneornil(L, idx)) { - return var; + return; } if (lua_istable(L, idx)) { @@ -429,16 +427,15 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, /* A "none" means start over */ if (strcmp("none", name) == 0) { - newVar = var; continue; } - actions::transformations::Transformation *tfn = \ + auto tfn = \ actions::transformations::Transformation::instantiate( "t:" + std::string(name)); // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->evaluate(newVar, t); + tfn->transform(var, t); } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ @@ -447,32 +444,31 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, delete tfn; } - return newVar; + return; } if (lua_isstring(L, idx)) { const char *name(NULL); name = reinterpret_cast(luaL_checkstring(L, idx)); - actions::transformations::Transformation *tfn = \ + auto tfn = \ actions::transformations::Transformation::instantiate( "t:" + std::string(name)); // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->evaluate(newVar, t); + tfn->transform(var, t); delete tfn; } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ + std::string(name)); } - return newVar; + return; } ms_dbg_a(t, 8, "SecRuleScript: Transformation parameter must be a " \ "transformation name or array of transformation names, but found " \ "" + std::string(lua_typename(L, idx)) + " (type " \ + std::to_string(lua_type(L, idx)) + ")"); - return newVar; } #endif diff --git a/src/engine/lua.h b/src/engine/lua.h index a33f28f8..452c7f49 100644 --- a/src/engine/lua.h +++ b/src/engine/lua.h @@ -79,8 +79,8 @@ class Lua { static int getvar(lua_State *L); static int getvars(lua_State *L); static int setvar(lua_State *L); - static std::string applyTransformations(lua_State *L, Transaction *t, - int idx, std::string var); + static void applyTransformations(lua_State *L, const Transaction *t, + int idx, std::string &var); LuaScriptBlob m_blob; #endif diff --git a/src/modsecurity.cc b/src/modsecurity.cc index 855facb3..93caa952 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -300,7 +300,6 @@ int ModSecurity::processContentOffset(const char *content, size_t len, while (!trans.empty()) { modsecurity::actions::transformations::Transformation *t; - std::string varValueRes; yajl_gen_map_open(g); yajl_gen_string(g, reinterpret_cast("transformation"), @@ -312,8 +311,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, t = modsecurity::actions::transformations::Transformation::instantiate( trans.back().str().c_str()); - varValueRes = t->evaluate(varValue, NULL); - varValue.assign(varValueRes); + t->transform(varValue, nullptr); trans.pop_back(); yajl_gen_string(g, reinterpret_cast("value"), diff --git a/src/operators/validate_utf8_encoding.cc b/src/operators/validate_utf8_encoding.cc index 3e17686f..cd2f064c 100644 --- a/src/operators/validate_utf8_encoding.cc +++ b/src/operators/validate_utf8_encoding.cc @@ -19,6 +19,14 @@ #include "src/operators/operator.h" + +constexpr int UNICODE_ERROR_CHARACTERS_MISSING = -1; +constexpr int UNICODE_ERROR_INVALID_ENCODING = -2; +constexpr int UNICODE_ERROR_OVERLONG_CHARACTER = -3; +constexpr int UNICODE_ERROR_RESTRICTED_CHARACTER = -4; +constexpr int UNICODE_ERROR_DECODING_ERROR = -5; + + namespace modsecurity { namespace operators { diff --git a/src/operators/validate_utf8_encoding.h b/src/operators/validate_utf8_encoding.h index e59eef58..2bd75dc8 100644 --- a/src/operators/validate_utf8_encoding.h +++ b/src/operators/validate_utf8_encoding.h @@ -22,13 +22,6 @@ #include "src/operators/operator.h" -#define UNICODE_ERROR_CHARACTERS_MISSING -1 -#define UNICODE_ERROR_INVALID_ENCODING -2 -#define UNICODE_ERROR_OVERLONG_CHARACTER -3 -#define UNICODE_ERROR_RESTRICTED_CHARACTER -4 -#define UNICODE_ERROR_DECODING_ERROR -5 - - namespace modsecurity { namespace operators { diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index e5d8183f..1b76005c 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include "modsecurity/rules_set.h" #include "src/operators/operator.h" @@ -323,49 +324,42 @@ void RuleWithActions::executeAction(Transaction *trans, inline void RuleWithActions::executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, - Transaction *trans, + const actions::transformations::Transformation &a, + std::string &value, + const Transaction *trans, TransformationResults *ret, std::string *path, int *nth) const { - std::string *oldValue = (*value).get(); - std::string newValue = a->evaluate(*oldValue, trans); - - if (newValue != *oldValue) { - auto u = std::make_shared(newValue); - if (m_containsMultiMatchAction) { - ret->push_back(std::make_pair(u, a->m_name)); - (*nth)++; - } - *value = u; + if (a.transform(value, trans) && + m_containsMultiMatchAction) { + ret.emplace_back(value, a.m_name); + (*nth)++; } if (path->empty()) { - path->append(*a->m_name.get()); + path->append(*a.m_name.get()); } else { - path->append("," + *a->m_name.get()); + path->append("," + *a.m_name.get()); } ms_dbg_a(trans, 9, " T (" + \ std::to_string(*nth) + ") " + \ - *a->m_name.get() + ": \"" + \ - utils::string::limitTo(80, newValue) +"\""); + *a.m_name.get() + ": \"" + \ + utils::string::limitTo(80, value) +"\""); } void RuleWithActions::executeTransformations( - Transaction *trans, const std::string &in, TransformationResults &ret) { + const Transaction *trans, const std::string &in, TransformationResults &ret) { int none = 0; int transformations = 0; std::string path(""); - auto value = std::make_shared(in); + auto value = in; if (m_containsMultiMatchAction == true) { /* keep the original value */ - ret.push_back(std::make_pair( - std::make_shared(*value), - std::make_shared(path))); + ret.emplace_back(value, + std::make_shared(path)); } for (Action *a : m_transformations) { @@ -385,15 +379,17 @@ void RuleWithActions::executeTransformations( } // FIXME: here the object needs to be a transformation already. - Transformation *t = dynamic_cast(a.get()); - executeTransformation(t, &value, trans, &ret, &path, + auto t = dynamic_cast(a.get()); + assert(t != nullptr); + executeTransformation(*t, value, trans, &ret, &path, &transformations); } } - for (Transformation *a : m_transformations) { + for (const Transformation *a : m_transformations) { + assert(a != nullptr); if (none == 0) { - executeTransformation(a, &value, trans, &ret, &path, + executeTransformation(*a, value, trans, &ret, &path, &transformations); } if (a->m_isNone) { @@ -408,7 +404,8 @@ void RuleWithActions::executeTransformations( if (m_ruleId != b.first) { continue; } - Transformation *a = dynamic_cast(b.second.get()); + auto a = dynamic_cast(b.second.get()); + assert(a != nullptr); if (a->m_isNone) { none++; } @@ -419,9 +416,10 @@ void RuleWithActions::executeTransformations( if (m_ruleId != b.first) { continue; } - Transformation *a = dynamic_cast(b.second.get()); + auto a = dynamic_cast(b.second.get()); + assert(a != nullptr); if (none == 0) { - executeTransformation(a, &value, trans, &ret, &path, + executeTransformation(*a, value, trans, &ret, &path, &transformations); } if (a->m_isNone) { @@ -436,9 +434,8 @@ void RuleWithActions::executeTransformations( } if (!m_containsMultiMatchAction) { - ret.push_back(std::make_pair( - std::make_shared(*value), - std::make_shared(path))); + ret.emplace_back(value, + std::make_shared(path)); } } diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index f54ffb5c..b043af5c 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -296,10 +296,9 @@ bool RuleWithOperator::evaluate(Transaction *trans, executeTransformations(trans, value, values); for (const auto &valueTemp : values) { - bool ret; - std::string valueAfterTrans = std::move(*valueTemp.first); + const auto &valueAfterTrans = valueTemp.first; - ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); + const bool ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); if (ret == true) { ruleMessage->m_match = m_operator->resolveMatchMessage(trans, diff --git a/src/utils/string.h b/src/utils/string.h index b0c3c17d..dbfb9b47 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -235,18 +235,18 @@ inline unsigned char *c2x(unsigned what, unsigned char *where) { } -inline std::string string_to_hex(const std::string& input) { - static const char* const lut = "0123456789ABCDEF"; - size_t len = input.length(); +inline std::string string_to_hex(std::string_view input) { + static const char* const lut = "0123456789abcdef"; - std::string output; - output.reserve(2 * len); - for (size_t i = 0; i < len; ++i) { - const unsigned char c = input[i]; - output.push_back(lut[c >> 4]); - output.push_back(lut[c & 15]); + std::string a(input.size()*2, 0); + char *d = a.data(); + + for (const unsigned char c : input) { + *d++ = lut[c >> 4]; + *d++ = lut[c & 15]; } - return output; + + return a; } diff --git a/test/coding_style_suppressions.txt b/test/coding_style_suppressions.txt index c2b1ea52..bba5a62c 100644 --- a/test/coding_style_suppressions.txt +++ b/test/coding_style_suppressions.txt @@ -13,7 +13,6 @@ ./src/utils/acmp.cc ./src/utils/acmp.h ./src/utils/mbedtls/ -./src/utils/md5.cc ./src/utils/md5.h ./src/utils/msc_tree.cc ./src/utils/msc_tree.h diff --git a/test/unit/unit.cc b/test/unit/unit.cc index 75fec137..5ebc9d3f 100644 --- a/test/unit/unit.cc +++ b/test/unit/unit.cc @@ -89,8 +89,10 @@ struct TransformationTest { return tfn; } - static UnitTestResult eval(ItemType &tfn, const UnitTest &t) { - return {1, tfn.evaluate(t.input, nullptr)}; + static UnitTestResult eval(const ItemType &tfn, const UnitTest &t) { + std::string ret = t.input; + tfn.transform(ret, nullptr); + return {1, ret}; } static bool check(const UnitTestResult &result, const UnitTest &t) { diff --git a/test/unit/unit_test.cc b/test/unit/unit_test.cc index dee4f1ae..b0060732 100644 --- a/test/unit/unit_test.cc +++ b/test/unit/unit_test.cc @@ -30,20 +30,6 @@ namespace modsecurity_test { -std::string string_to_hex(const std::string& input) { - static const char* const lut = "0123456789ABCDEF"; - size_t len = input.length(); - - std::string output; - output.reserve(2 * len); - for (size_t i = 0; i < len; ++i) { - const unsigned char c = input[i]; - output.push_back(lut[c >> 4]); - output.push_back(lut[c & 15]); - } - return output; -} - void replaceAll(std::string *s, const std::string &search, const char replace) { for (size_t pos = 0; ; pos += 0) { From 3ff72fbbc526b0c1dd17e63f61791c126d125831 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 01:48:38 +0000 Subject: [PATCH 50/75] Perform ParityEven7bit, ParityOdd7bit & ParityZero7bit transformations in-place - Refactored to share implementations of ParityEven7bit & ParityOdd7bit. --- .../transformations/parity_even_7bit.cc | 43 +----------------- .../transformations/parity_even_7bit.h | 23 +++++++++- .../transformations/parity_odd_7bit.cc | 44 +------------------ src/actions/transformations/parity_odd_7bit.h | 1 - .../transformations/parity_zero_7bit.cc | 38 ++++------------ .../transformations/parity_zero_7bit.h | 1 - 6 files changed, 33 insertions(+), 117 deletions(-) diff --git a/src/actions/transformations/parity_even_7bit.cc b/src/actions/transformations/parity_even_7bit.cc index f2992240..d9327b9e 100644 --- a/src/actions/transformations/parity_even_7bit.cc +++ b/src/actions/transformations/parity_even_7bit.cc @@ -15,53 +15,12 @@ #include "parity_even_7bit.h" -#include - namespace modsecurity::actions::transformations { bool ParityEven7bit::transform(std::string &value, const Transaction *trans) const { - if (value.empty()) return false; - - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - std::memcpy(input, value.c_str(), value.length()+1); - - const auto ret = inplace(input, value.length()); - - value.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; -} - -bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) { - uint64_t i; - - i = 0; - while (i < input_len) { - unsigned int x = input[i]; - - input[i] ^= input[i] >> 4; - input[i] &= 0xf; - - if ((0x6996 >> input[i]) & 1) { - input[i] = x | 0x80; - } else { - input[i] = x & 0x7f; - } - i++; - } - - return true; + return ParityEven7bit::inplace(value); } diff --git a/src/actions/transformations/parity_even_7bit.h b/src/actions/transformations/parity_even_7bit.h index 41010d62..786f72e4 100644 --- a/src/actions/transformations/parity_even_7bit.h +++ b/src/actions/transformations/parity_even_7bit.h @@ -26,7 +26,28 @@ class ParityEven7bit : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - static bool inplace(unsigned char *input, uint64_t input_len); + + template + static bool inplace(std::string &value) { + if (value.empty()) return false; + + for(auto &c : value) { + auto &uc = reinterpret_cast(c); + unsigned int x = uc; + + uc ^= uc >> 4; + uc &= 0xf; + + const bool condition = (0x6996 >> uc) & 1; + if (even ? condition : !condition) { + uc = x | 0x80; + } else { + uc = x & 0x7f; + } + } + + return true; + } }; } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_odd_7bit.cc b/src/actions/transformations/parity_odd_7bit.cc index f8192ef3..865a2754 100644 --- a/src/actions/transformations/parity_odd_7bit.cc +++ b/src/actions/transformations/parity_odd_7bit.cc @@ -14,54 +14,14 @@ */ #include "parity_odd_7bit.h" - -#include +#include "parity_even_7bit.h" namespace modsecurity::actions::transformations { bool ParityOdd7bit::transform(std::string &value, const Transaction *trans) const { - if (value.empty()) return false; - - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - const auto ret = inplace(input, value.length()); - - value.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; -} - -bool ParityOdd7bit::inplace(unsigned char *input, uint64_t input_len) { - uint64_t i; - - i = 0; - while (i < input_len) { - unsigned int x = input[i]; - - input[i] ^= input[i] >> 4; - input[i] &= 0xf; - - if ((0x6996 >> input[i]) & 1) { - input[i] = x & 0x7f; - } else { - input[i] = x | 0x80; - } - i++; - } - - return true; + return ParityEven7bit::inplace(value); } diff --git a/src/actions/transformations/parity_odd_7bit.h b/src/actions/transformations/parity_odd_7bit.h index 1afa1327..d0a1583c 100644 --- a/src/actions/transformations/parity_odd_7bit.h +++ b/src/actions/transformations/parity_odd_7bit.h @@ -26,7 +26,6 @@ class ParityOdd7bit : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - static bool inplace(unsigned char *input, uint64_t input_len); }; } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_zero_7bit.cc b/src/actions/transformations/parity_zero_7bit.cc index ef80b74d..77ad0514 100644 --- a/src/actions/transformations/parity_zero_7bit.cc +++ b/src/actions/transformations/parity_zero_7bit.cc @@ -15,46 +15,24 @@ #include "parity_zero_7bit.h" -#include - namespace modsecurity::actions::transformations { -bool ParityZero7bit::transform(std::string &value, const Transaction *trans) const { +static inline bool inplace(std::string &value) { if (value.empty()) return false; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - const auto ret = inplace(input, value.length()); - - value.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; -} - - -bool ParityZero7bit::inplace(unsigned char *input, uint64_t input_len) { - uint64_t i; - - i = 0; - while (i < input_len) { - input[i] &= 0x7f; - i++; + for(auto &c : value) { + ((unsigned char&)c) &= 0x7f; } return true; } +bool ParityZero7bit::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_zero_7bit.h b/src/actions/transformations/parity_zero_7bit.h index af47f7c5..c7f27d74 100644 --- a/src/actions/transformations/parity_zero_7bit.h +++ b/src/actions/transformations/parity_zero_7bit.h @@ -26,7 +26,6 @@ class ParityZero7bit : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - static bool inplace(unsigned char *input, uint64_t input_len); }; } // namespace modsecurity::actions::transformations From 13203ae5e7dba5ce8e80fd720573ca6e1e3155e6 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 07:09:26 -0700 Subject: [PATCH 51/75] Perform CmdLine transformation in-place --- src/actions/transformations/cmd_line.cc | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/actions/transformations/cmd_line.cc b/src/actions/transformations/cmd_line.cc index cac1d2df..8db1529d 100644 --- a/src/actions/transformations/cmd_line.cc +++ b/src/actions/transformations/cmd_line.cc @@ -20,10 +20,10 @@ namespace modsecurity::actions::transformations { bool CmdLine::transform(std::string &value, const Transaction *trans) const { - std::string ret; - int space = 0; + char *d = value.data(); + bool space = false; - for (auto& a : value) { + for (const auto& a : value) { switch (a) { /* remove some characters */ case '"': @@ -39,9 +39,9 @@ bool CmdLine::transform(std::string &value, const Transaction *trans) const { case '\t': case '\r': case '\n': - if (space == 0) { - ret.append(" "); - space++; + if (space == false) { + *d++ = ' '; + space = true; } break; @@ -49,23 +49,24 @@ bool CmdLine::transform(std::string &value, const Transaction *trans) const { case '/': case '(': if (space) { - ret.pop_back(); + d--; } - space = 0; - ret.append(&a, 1); + space = false; + *d++ = a; break; /* copy normal characters */ default : char b = std::tolower(a); - ret.append(&b, 1); - space = 0; + *d++ = b; + space = false; break; } } - const auto changed = ret != value; - value = ret; + const auto new_len = d - value.c_str(); + const auto changed = new_len != value.length(); + value.resize(new_len); return changed; } From 1236d9a7cda62c58e10dba8d22ad801b2d7f353b Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 07:14:11 -0700 Subject: [PATCH 52/75] Perform CompressWhitespace transformation in-place --- .../transformations/compress_whitespace.cc | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/actions/transformations/compress_whitespace.cc b/src/actions/transformations/compress_whitespace.cc index 32c22a25..065b4ee0 100644 --- a/src/actions/transformations/compress_whitespace.cc +++ b/src/actions/transformations/compress_whitespace.cc @@ -25,29 +25,27 @@ CompressWhitespace::CompressWhitespace(const std::string &action) } bool CompressWhitespace::transform(std::string &value, const Transaction *trans) const { + bool inWhiteSpace = false; - std::string a; - int inWhiteSpace = 0; - int i = 0; + auto d = value.data(); - while (i < value.size()) { - if (isspace(value[i])) { + for(const auto c : value) { + if (isspace(c)) { if (inWhiteSpace) { - i++; continue; } else { - inWhiteSpace = 1; - a.append(" ", 1); + inWhiteSpace = true; + *d++ = ' '; } } else { - inWhiteSpace = 0; - a.append(&value.at(i), 1); + inWhiteSpace = false; + *d++ = c; } - i++; } - const auto changed = a != value; - value = a; + const auto new_len = d - value.c_str(); + const auto changed = new_len != value.length(); + value.resize(new_len); return changed; } From 150502599068b721c7be6e8db5c8da39adff3b0e Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 07:21:22 -0700 Subject: [PATCH 53/75] Perform RemoveNulls & RemoveWhitespace transformations in-place - Refactored to share implementation. --- src/actions/transformations/remove_nulls.cc | 19 ++----------- src/actions/transformations/remove_nulls.h | 14 ++++++++++ .../transformations/remove_whitespace.cc | 28 ++++++------------- 3 files changed, 25 insertions(+), 36 deletions(-) diff --git a/src/actions/transformations/remove_nulls.cc b/src/actions/transformations/remove_nulls.cc index bda34bbe..1d3cc552 100644 --- a/src/actions/transformations/remove_nulls.cc +++ b/src/actions/transformations/remove_nulls.cc @@ -19,23 +19,8 @@ namespace modsecurity::actions::transformations { -bool RemoveNulls::transform(std::string &val, const Transaction *trans) const { - size_t i = 0; - std::string transformed_value; - transformed_value.reserve(val.size()); - - while (i < val.size()) { - if (val.at(i) == '\0') { - // do nothing; continue on to next char in original val - } else { - transformed_value += val.at(i); - } - i++; - } - - const auto changed = transformed_value != val; - val = transformed_value; - return changed; +bool RemoveNulls::transform(std::string &value, const Transaction *trans) const { + return remove_if(value, [](const auto c) { return c == '\0'; }); } diff --git a/src/actions/transformations/remove_nulls.h b/src/actions/transformations/remove_nulls.h index 56df24c8..163f9ddf 100644 --- a/src/actions/transformations/remove_nulls.h +++ b/src/actions/transformations/remove_nulls.h @@ -18,6 +18,8 @@ #include "transformation.h" +#include + namespace modsecurity::actions::transformations { class RemoveNulls : public Transformation { @@ -26,6 +28,18 @@ class RemoveNulls : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; + + template + static bool remove_if(std::string &val, Pred pred) { + const auto old_size = val.size(); + + val.erase( + std::remove_if( + val.begin(), val.end(), pred), + val.end()); + + return val.size() != old_size; + } }; } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_whitespace.cc b/src/actions/transformations/remove_whitespace.cc index 8cee80c9..934f1d29 100644 --- a/src/actions/transformations/remove_whitespace.cc +++ b/src/actions/transformations/remove_whitespace.cc @@ -15,6 +15,8 @@ #include "remove_whitespace.h" +#include "remove_nulls.h" + namespace modsecurity::actions::transformations { @@ -23,30 +25,18 @@ RemoveWhitespace::RemoveWhitespace(const std::string &action) this->action_kind = 1; } -bool RemoveWhitespace::transform(std::string &val, const Transaction *trans) const { - std::string transformed_value; - transformed_value.reserve(val.size()); - - size_t i = 0; +bool RemoveWhitespace::transform(std::string &value, const Transaction *trans) const { const char nonBreakingSpaces = 0xa0; const char nonBreakingSpaces2 = 0xc2; - // loop through all the chars - while (i < val.size()) { + auto pred = [](const auto c) { // remove whitespaces and non breaking spaces (NBSP) - if (std::isspace(static_cast(val[i])) - || (val[i] == nonBreakingSpaces) - || val[i] == nonBreakingSpaces2) { - // don't copy; continue on to next char in original val - } else { - transformed_value += val.at(i); - } - i++; - } + return std::isspace(static_cast(c)) + || c == nonBreakingSpaces + || c == nonBreakingSpaces2; + }; - const auto changed = transformed_value != val; - val = transformed_value; - return changed; + return RemoveNulls::remove_if(value, pred); } From da775eca81e2b4c7b74cf5287e4fa016d5a73b12 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 08:41:18 -0700 Subject: [PATCH 54/75] Perform ReplaceNulls transformation in-place --- src/actions/transformations/replace_nulls.cc | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/actions/transformations/replace_nulls.cc b/src/actions/transformations/replace_nulls.cc index c59ceb87..479f2f5a 100644 --- a/src/actions/transformations/replace_nulls.cc +++ b/src/actions/transformations/replace_nulls.cc @@ -23,21 +23,16 @@ ReplaceNulls::ReplaceNulls(const std::string &action) this->action_kind = 1; } -bool ReplaceNulls::transform(std::string &val, const Transaction *trans) const { - int64_t i; - std::string value(val); +bool ReplaceNulls::transform(std::string &value, const Transaction *trans) const { + bool changed = false; - i = 0; - while (i < value.size()) { - if (value.at(i) == '\0') { - value[i] = ' '; - } else { - i++; + for(auto &c : value) { + if (c == '\0') { + c = ' '; + changed = true; } } - const auto changed = val != value; - val = value; return changed; } From 74d150c068cceaca76300f0003be6e2d152d975f Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 07:30:11 -0700 Subject: [PATCH 55/75] Perform RemoveCommentsChar, RemoveComments & ReplaceComments transformations in-place --- .../transformations/remove_comments.cc | 46 ++++++------- .../transformations/remove_comments_char.cc | 64 +++++++++---------- .../transformations/replace_comments.cc | 52 +++++++-------- 3 files changed, 76 insertions(+), 86 deletions(-) diff --git a/src/actions/transformations/remove_comments.cc b/src/actions/transformations/remove_comments.cc index 1515675c..5f3edaef 100644 --- a/src/actions/transformations/remove_comments.cc +++ b/src/actions/transformations/remove_comments.cc @@ -19,41 +19,34 @@ namespace modsecurity::actions::transformations { -bool RemoveComments::transform(std::string &value, const Transaction *trans) const { - std::string ret; - unsigned char *input; +static inline int inplace(std::string &value) { + auto input = reinterpret_cast(value.data()); + const auto input_len = value.length(); + bool changed = false, incomment = false; + std::string::size_type i = 0, j = 0; - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - uint64_t input_len = value.size(); - uint64_t i, j, incomment; - - i = j = incomment = 0; while (i < input_len) { - if (incomment == 0) { + if (!incomment) { if ((input[i] == '/') && (i + 1 < input_len) && (input[i + 1] == '*')) { - incomment = 1; + incomment = true; + changed = true; i += 2; } else if ((input[i] == '<') && (i + 1 < input_len) && (input[i + 1] == '!') && (i + 2 < input_len) && (input[i+2] == '-') && (i + 3 < input_len) && (input[i + 3] == '-')) { - incomment = 1; + incomment = true; + changed = true; i += 4; } else if ((input[i] == '-') && (i + 1 < input_len) && (input[i + 1] == '-')) { input[i] = ' '; + changed = true; break; } else if (input[i] == '#') { input[i] = ' '; + changed = true; break; } else { input[j] = input[i]; @@ -63,7 +56,7 @@ bool RemoveComments::transform(std::string &value, const Transaction *trans) con } else { if ((input[i] == '*') && (i + 1 < input_len) && (input[i + 1] == '/')) { - incomment = 0; + incomment = false; i += 2; input[j] = input[i]; i++; @@ -71,7 +64,7 @@ bool RemoveComments::transform(std::string &value, const Transaction *trans) con } else if ((input[i] == '-') && (i + 1 < input_len) && (input[i + 1] == '-') && (i + 2 < input_len) && (input[i+2] == '>')) { - incomment = 0; + incomment = false; i += 3; input[j] = input[i]; i++; @@ -86,13 +79,14 @@ bool RemoveComments::transform(std::string &value, const Transaction *trans) con input[j++] = ' '; } - ret.assign(reinterpret_cast(input), j); - free(input); - - const auto changed = ret != value; - value = ret; + value.resize(j); return changed; } +bool RemoveComments::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_comments_char.cc b/src/actions/transformations/remove_comments_char.cc index 7a4763d3..2eeb86f6 100644 --- a/src/actions/transformations/remove_comments_char.cc +++ b/src/actions/transformations/remove_comments_char.cc @@ -23,43 +23,43 @@ RemoveCommentsChar::RemoveCommentsChar(const std::string &action) this->action_kind = 1; } -bool RemoveCommentsChar::transform(std::string &val, const Transaction *trans) const { - size_t i = 0; - std::string transformed_value; - transformed_value.reserve(val.size()); +bool RemoveCommentsChar::transform(std::string &value, const Transaction *trans) const { + char *d = value.data(); + const char *s = d; + const char *e = s + value.size(); - while (i < val.size()) { - if (val.at(i) == '/' - && (i+1 < val.size()) && val.at(i+1) == '*') { - i += 2; - } else if (val.at(i) == '*' - && (i+1 < val.size()) && val.at(i+1) == '/') { - i += 2; - } else if (val.at(i) == '<' - && (i+1 < val.size()) - && val.at(i+1) == '!' - && (i+2 < val.size()) - && val.at(i+2) == '-' - && (i+3 < val.size()) - && val.at(i+3) == '-') { - i += 4; - } else if (val.at(i) == '-' - && (i+1 < val.size()) && val.at(i+1) == '-' - && (i+2 < val.size()) && val.at(i+2) == '>') { - i += 3; - } else if (val.at(i) == '-' - && (i+1 < val.size()) && val.at(i+1) == '-') { - i += 2; - } else if (val.at(i) == '#') { - i += 1; + while (s < e) { + if (*s == '/' + && (s+1 < e) && *(s+1) == '*') { + s += 2; + } else if (*s == '*' + && (s+1 < e) && *(s+1) == '/') { + s += 2; + } else if (*s == '<' + && (s+1 < e) + && *(s+1) == '!' + && (s+2 < e) + && *(s+2) == '-' + && (s+3 < e) + && *(s+3) == '-') { + s += 4; + } else if (*s == '-' + && (s+1 < e) && *(s+1) == '-' + && (s+2 < e) && *(s+2) == '>') { + s += 3; + } else if (*s == '-' + && (s+1 < e) && *(s+1) == '-') { + s += 2; + } else if (*s == '#') { + s += 1; } else { - transformed_value += val.at(i); - i++; + *d++ = *s++; } } - const auto changed = transformed_value != val; - val = transformed_value; + const auto changed = d != s; + const auto new_len = d - value.c_str(); + value.resize(new_len); return changed; } diff --git a/src/actions/transformations/replace_comments.cc b/src/actions/transformations/replace_comments.cc index b1aeecf9..a6bab972 100644 --- a/src/actions/transformations/replace_comments.cc +++ b/src/actions/transformations/replace_comments.cc @@ -19,36 +19,28 @@ namespace modsecurity::actions::transformations { -ReplaceComments::ReplaceComments(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} +static inline bool inplace(std::string &value) { + auto input = reinterpret_cast(value.data()); + const auto input_len = value.length(); + bool changed = false, incomment = false; + std::string::size_type i = 0, j = 0; - -bool ReplaceComments::transform(std::string &value, const Transaction *trans) const { - uint64_t i, j, incomment; - - char *input = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(input, value.c_str(), value.size() + 1); - input[value.size()] = '\0'; - - i = j = incomment = 0; - while (i < value.size()) { - if (incomment == 0) { - if ((input[i] == '/') && (i + 1 < value.size()) + while (i < input_len) { + if (!incomment) { + if ((input[i] == '/') && (i + 1 < input_len) && (input[i + 1] == '*')) { - incomment = 1; + incomment = true; i += 2; + changed = true; } else { input[j] = input[i]; i++; j++; } } else { - if ((input[i] == '*') && (i + 1 < value.size()) + if ((input[i] == '*') && (i + 1 < input_len) && (input[i + 1] == '/')) { - incomment = 0; + incomment = false; i += 2; input[j] = ' '; j++; @@ -62,16 +54,20 @@ bool ReplaceComments::transform(std::string &value, const Transaction *trans) co input[j++] = ' '; } - - std::string resp; - resp.append(reinterpret_cast(input), j); - - free(input); - - const auto changed = resp != value; - value = resp; + value.resize(j); return changed; } +ReplaceComments::ReplaceComments(const std::string &action) + : Transformation(action) { + this->action_kind = 1; +} + + +bool ReplaceComments::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + } // namespace modsecurity::actions::transformations From 2915ee60e23587e9e0ad4d1c1f13a43b9a208a63 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 07:45:16 -0700 Subject: [PATCH 56/75] Perform Trim, TrimLeft & TrimRight transformations in-place --- src/actions/transformations/trim.cc | 45 ++++++++++++----------- src/actions/transformations/trim.h | 8 ++-- src/actions/transformations/trim_left.cc | 6 +-- src/actions/transformations/trim_right.cc | 6 +-- 4 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/actions/transformations/trim.cc b/src/actions/transformations/trim.cc index a5515346..bc90b4ec 100644 --- a/src/actions/transformations/trim.cc +++ b/src/actions/transformations/trim.cc @@ -15,36 +15,43 @@ #include "trim.h" +#include + namespace modsecurity::actions::transformations { -std::string *Trim::ltrim(std::string *s) { - s->erase( - s->begin(), - std::find_if(s->begin(), s->end(), [](unsigned char c) { +bool Trim::ltrim(std::string &s) { + auto it = std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isspace(c); - }) - ); + }); - return s; + const bool changed = it != s.begin(); + + s.erase(s.begin(), it); + + return changed; } -std::string *Trim::rtrim(std::string *s) { - s->erase( - std::find_if(s->rbegin(), s->rend(), [](unsigned char c) { +bool Trim::rtrim(std::string &s) { + auto it = std::find_if(s.rbegin(), s.rend(), [](unsigned char c) { return !std::isspace(c); - }).base(), - s->end() - ); + }).base(); - return s; + const bool changed = it != s.end(); + + s.erase(it, s.end()); + + return changed; } -std::string *Trim::trim(std::string *s) { - return ltrim(rtrim(s)); +bool Trim::trim(std::string &s) { + bool changed = false; + changed |= rtrim(s); + changed |= ltrim(s); + return changed; } @@ -55,11 +62,7 @@ Trim::Trim(const std::string &action) bool Trim::transform(std::string &value, const Transaction *trans) const { - std::string ret(value); - this->trim(&ret); - const auto changed = ret != value; - value = ret; - return changed; + return trim(value); } diff --git a/src/actions/transformations/trim.h b/src/actions/transformations/trim.h index 3b0e82d9..0e3d26f6 100644 --- a/src/actions/transformations/trim.h +++ b/src/actions/transformations/trim.h @@ -26,9 +26,11 @@ class Trim : public Transformation { bool transform(std::string &value, const Transaction *trans) const override; - static std::string *ltrim(std::string *s); - static std::string *rtrim(std::string *s); - static std::string *trim(std::string *s); + protected: + + static bool ltrim(std::string &s); + static bool rtrim(std::string &s); + static bool trim(std::string &s); }; } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/trim_left.cc b/src/actions/transformations/trim_left.cc index c141727a..10276acf 100644 --- a/src/actions/transformations/trim_left.cc +++ b/src/actions/transformations/trim_left.cc @@ -26,11 +26,7 @@ TrimLeft::TrimLeft(const std::string &action) } bool TrimLeft::transform(std::string &value, const Transaction *trans) const { - std::string ret(value); - this->ltrim(&ret); - const auto changed = ret != value; - value = ret; - return changed; + return ltrim(value); } diff --git a/src/actions/transformations/trim_right.cc b/src/actions/transformations/trim_right.cc index b95b63aa..aa38c348 100644 --- a/src/actions/transformations/trim_right.cc +++ b/src/actions/transformations/trim_right.cc @@ -25,11 +25,7 @@ TrimRight::TrimRight(const std::string &action) } bool TrimRight::transform(std::string &value, const Transaction *trans) const { - std::string ret(value); - this->rtrim(&ret); - const auto changed = ret != value; - value = ret; - return changed; + return rtrim(value); } From fd8a979463c06a50ecd45687949a7a8a3e1cac90 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 07:55:41 -0700 Subject: [PATCH 57/75] Perform SqlHexDecode transformation in-place - Validate buffer size before accessing data. The previous implementation would only check that there was a character available in the buffer but could continue processing/reading characters from an hex representation without checking bounds. - Removed inplace & mytolower helper functions from the class, as they're only referenced by the implementation. - Removed duplicate VALID_HEX & ISODIGIT macros, already in src/utils/string.h. --- src/actions/transformations/sql_hex_decode.cc | 95 +++++++------------ src/actions/transformations/sql_hex_decode.h | 9 -- 2 files changed, 33 insertions(+), 71 deletions(-) diff --git a/src/actions/transformations/sql_hex_decode.cc b/src/actions/transformations/sql_hex_decode.cc index 41189f92..8f19e619 100644 --- a/src/actions/transformations/sql_hex_decode.cc +++ b/src/actions/transformations/sql_hex_decode.cc @@ -23,79 +23,50 @@ namespace modsecurity::actions::transformations { -#ifndef VALID_HEX -#define VALID_HEX(X) (((X >= '0') && (X <= '9')) \ - || ((X >= 'a') && (X <= 'f')) \ - || ((X >= 'A') && (X <= 'F'))) -#endif -#ifndef ISODIGIT -#define ISODIGIT(X) ((X >= '0') && (X <= '7')) -#endif - -bool SqlHexDecode::transform(std::string &value, const Transaction *trans) const { - std::string ret; - unsigned char *input; - int size = 0; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), size); - free(input); - - const auto changed = ret != value; - value = ret; - return changed; +static inline int mytolower(int ch) { + if (ch >= 'A' && ch <= 'Z') + return ('a' + ch - 'A'); + else + return ch; } - -int SqlHexDecode::inplace(unsigned char *data, int len) { - unsigned char *d, *begin = data; - int count = 0; - - if ((data == NULL) || (len == 0)) { - return 0; +static inline bool inplace(std::string &value) { + if (value.empty()) { + return false; } - for (d = data; (++count < len) && *data; *d++ = *data++) { - if (*data != '0') { - continue; - } - ++data; - ++count; - if (mytolower(*data) != 'x') { - data--; - count--; - continue; - } + auto d = reinterpret_cast(value.data()); + const unsigned char *data = d; + const auto end = data + value.size(); - data++; - ++count; + bool changed = false; - // Do we need to keep "0x" if no hexa after? - if (!VALID_HEX(data[0]) || !VALID_HEX(data[1])) { - data -= 2; - count -= 2; - continue; + while (data < end) { + if (data + 3 < end + && *data == '0' + && mytolower(*(data + 1)) == 'x' + && VALID_HEX(*(data + 2)) && VALID_HEX(*(data + 3))) { + data += 2; // skip '0x' + do { + *d++ = utils::string::x2c(data); + data += 2; + } while ((data + 1 < end) && VALID_HEX(*data) && VALID_HEX(*(data + 1))); + changed = true; } - - while (VALID_HEX(data[0]) && VALID_HEX(data[1])) { - *d++ = utils::string::x2c(data); - data += 2; - count += 2; + else { + *d++ = *data++; } } *d = '\0'; - return strlen(reinterpret_cast(begin)); + + value.resize(d - reinterpret_cast(value.c_str())); + return changed; +} + + +bool SqlHexDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); } diff --git a/src/actions/transformations/sql_hex_decode.h b/src/actions/transformations/sql_hex_decode.h index a92a0a2b..44f45d17 100644 --- a/src/actions/transformations/sql_hex_decode.h +++ b/src/actions/transformations/sql_hex_decode.h @@ -26,15 +26,6 @@ class SqlHexDecode : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - - static int inplace(unsigned char *data, int len); - - static int mytolower(int ch) { - if (ch >= 'A' && ch <= 'Z') - return ('a' + ch - 'A'); - else - return ch; - } }; } // namespace modsecurity::actions::transformations From 4670710376e9b80f2d1a151f627c08d3c086d0b7 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 08:06:00 -0700 Subject: [PATCH 58/75] Perform LowerCase & UpperCase transformations in-place - Refactored to share implementation and reduce code duplication. --- src/actions/transformations/lower_case.cc | 16 ++++------------ src/actions/transformations/lower_case.h | 15 +++++++++++++++ src/actions/transformations/upper_case.cc | 19 +++++++------------ 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/actions/transformations/lower_case.cc b/src/actions/transformations/lower_case.cc index 0ea1864c..080429d9 100644 --- a/src/actions/transformations/lower_case.cc +++ b/src/actions/transformations/lower_case.cc @@ -16,7 +16,7 @@ #include "lower_case.h" -#include +#include namespace modsecurity::actions::transformations { @@ -26,17 +26,9 @@ LowerCase::LowerCase(const std::string &a) : Transformation(a) { } -bool LowerCase::transform(std::string &val, const Transaction *trans) const { - std::locale loc; - std::string value(val); - - for (std::string::size_type i=0; i < value.length(); ++i) { - value[i] = std::tolower(value[i], loc); - } - - const auto changed = val != value; - val = value; - return changed; +bool LowerCase::transform(std::string &value, const Transaction *trans) const { + return convert(value, [](auto c) { + return std::tolower(c); }); } diff --git a/src/actions/transformations/lower_case.h b/src/actions/transformations/lower_case.h index bbb51272..7bdf2d84 100644 --- a/src/actions/transformations/lower_case.h +++ b/src/actions/transformations/lower_case.h @@ -18,6 +18,8 @@ #include "transformation.h" +#include + namespace modsecurity::actions::transformations { class LowerCase : public Transformation { @@ -25,6 +27,19 @@ class LowerCase : public Transformation { explicit LowerCase(const std::string &action); bool transform(std::string &value, const Transaction *trans) const override; + + template + static bool convert(std::string &val, Operation op) { + bool changed = false; + + std::transform(val.begin(), val.end(), val.data(), + [&](auto c) { + const auto nc = op(c); + if(nc != c) changed = true; + return nc; }); + + return changed; + } }; } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/upper_case.cc b/src/actions/transformations/upper_case.cc index 2b8ad1d9..f811bcbb 100644 --- a/src/actions/transformations/upper_case.cc +++ b/src/actions/transformations/upper_case.cc @@ -16,7 +16,10 @@ #include "upper_case.h" -#include +#include + +#include "lower_case.h" + namespace modsecurity::actions::transformations { @@ -25,17 +28,9 @@ UpperCase::UpperCase(const std::string &a) : Transformation(a) { } -bool UpperCase::transform(std::string &val, const Transaction *trans) const { - std::string value(val); - std::locale loc; - - for (std::string::size_type i=0; i < value.length(); ++i) { - value[i] = std::toupper(value[i], loc); - } - - const auto changed = val != value; - val = value; - return changed; +bool UpperCase::transform(std::string &value, const Transaction *trans) const { + return LowerCase::convert(value, [](auto c) + { return std::toupper(c); }); } From e687140d0583ae5e85e248bdb364eec8b952a921 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 08:12:00 -0700 Subject: [PATCH 59/75] Perform HexDecode transformation in-place - Removed inplace helper function from the class, as it's only referenced by the implementation. --- src/actions/transformations/hex_decode.cc | 44 +++++++---------------- src/actions/transformations/hex_decode.h | 2 -- 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/src/actions/transformations/hex_decode.cc b/src/actions/transformations/hex_decode.cc index 5866079b..1b43b6cd 100644 --- a/src/actions/transformations/hex_decode.cc +++ b/src/actions/transformations/hex_decode.cc @@ -21,46 +21,26 @@ namespace modsecurity::actions::transformations { -bool HexDecode::transform(std::string &value, const Transaction *trans) const { - std::string ret; - unsigned char *input; - int size = 0; +static inline int inplace(std::string &value) { + if (value.empty()) return false; - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); + const auto len = value.length(); + auto d = reinterpret_cast(value.data()); + const auto data = d; - if (input == NULL) { - return ""; + for (int i = 0; i <= len - 2; i += 2) { + *d++ = utils::string::x2c(&data[i]); } - memcpy(input, value.c_str(), value.length()+1); + *d = '\0'; - size = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), size); - free(input); - - const auto changed = ret != value; - value = ret; - return changed; + value.resize(d - data); + return true; } -int HexDecode::inplace(unsigned char *data, int len) { - unsigned char *d = data; - int count = 0; - - if ((data == NULL) || (len == 0)) { - return 0; - } - - for (int i = 0;i <= len - 2;i += 2) { - *d++ = utils::string::x2c(&data[i]); - count++; - } - *d = '\0'; - - return count; +bool HexDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); } diff --git a/src/actions/transformations/hex_decode.h b/src/actions/transformations/hex_decode.h index 4239c86d..158f91aa 100644 --- a/src/actions/transformations/hex_decode.h +++ b/src/actions/transformations/hex_decode.h @@ -26,8 +26,6 @@ class HexDecode : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - - static int inplace(unsigned char *data, int len); }; } // namespace modsecurity::actions::transformations From 727f2bf840dff972bd6ab41316884645171fedef Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 08:24:31 -0700 Subject: [PATCH 60/75] Perform CssDecode transformation in-place - Removed inplace helper function from the class, as it's only referenced by the implementation. --- src/actions/transformations/css_decode.cc | 50 ++++++++--------------- src/actions/transformations/css_decode.h | 2 - 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/actions/transformations/css_decode.cc b/src/actions/transformations/css_decode.cc index 7f6938ac..c5de63f7 100644 --- a/src/actions/transformations/css_decode.cc +++ b/src/actions/transformations/css_decode.cc @@ -21,25 +21,6 @@ namespace modsecurity::actions::transformations { -bool CssDecode::transform(std::string &value, const Transaction *trans) const { - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - CssDecode::css_decode_inplace(reinterpret_cast(tmp), - value.size()); - - std::string ret(tmp, 0, value.size()); - free(tmp); - - const auto changed = ret != value; - value = ret; - return changed; -} - - /** * Decode a string that contains CSS-escaped characters. * @@ -47,15 +28,13 @@ bool CssDecode::transform(std::string &value, const Transaction *trans) const { * http://www.w3.org/TR/REC-CSS2/syndata.html#q4 * http://www.unicode.org/roadmaps/ */ -int CssDecode::css_decode_inplace(unsigned char *input, int64_t input_len) { - unsigned char *d = (unsigned char *)input; - int64_t i, j, count; +static inline bool css_decode_inplace(std::string &val) { + const auto input_len = val.length(); + auto input = reinterpret_cast(val.data()); + auto d = input; + bool changed = false; - if (input == NULL) { - return -1; - } - - i = count = 0; + std::string::size_type i = 0; while (i < input_len) { /* Is the character a backslash? */ if (input[i] == '\\') { @@ -64,7 +43,7 @@ int CssDecode::css_decode_inplace(unsigned char *input, int64_t input_len) { i++; /* We are not going to need the backslash. */ /* Check for 1-6 hex characters following the backslash */ - j = 0; + std::string::size_type j = 0; while ((j < 6) && (i + j < input_len) && (VALID_HEX(input[i + j]))) { @@ -146,37 +125,44 @@ int CssDecode::css_decode_inplace(unsigned char *input, int64_t input_len) { } /* Move over. */ - count++; i += j; + + changed = true; } else if (input[i] == '\n') { /* No hexadecimal digits after backslash */ /* A newline character following backslash is ignored. */ i++; + changed = true; } else { /* The character after backslash is not a hexadecimal digit, * nor a newline. */ /* Use one character after backslash as is. */ *d++ = input[i++]; - count++; } } else { /* No characters after backslash. */ /* Do not include backslash in output *(continuation to nothing) */ i++; + changed = true; } } else { /* Character is not a backslash. */ /* Copy one normal character to output. */ *d++ = input[i++]; - count++; } } /* Terminate output string. */ *d = '\0'; - return count; + val.resize(d - input); + return changed; +} + + +bool CssDecode::transform(std::string &value, const Transaction *trans) const { + return css_decode_inplace(value); } diff --git a/src/actions/transformations/css_decode.h b/src/actions/transformations/css_decode.h index 04418149..67535a9a 100644 --- a/src/actions/transformations/css_decode.h +++ b/src/actions/transformations/css_decode.h @@ -26,8 +26,6 @@ class CssDecode : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - - static int css_decode_inplace(unsigned char *input, int64_t input_len); }; } // namespace modsecurity::actions::transformations From a520369da025fe203c9302e643374eb5e76e0718 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 08:28:04 -0700 Subject: [PATCH 61/75] Perform EscapeSeqDecode transformation in-place - Removed ansi_c_sequences_decode_inplace helper function from the class, as it's only referenced by the implementation. --- .../transformations/escape_seq_decode.cc | 41 +++++++------------ .../transformations/escape_seq_decode.h | 1 - 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/actions/transformations/escape_seq_decode.cc b/src/actions/transformations/escape_seq_decode.cc index a0dccb53..29006144 100644 --- a/src/actions/transformations/escape_seq_decode.cc +++ b/src/actions/transformations/escape_seq_decode.cc @@ -26,12 +26,13 @@ EscapeSeqDecode::EscapeSeqDecode(const std::string &action) } -int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, - int input_len) { - unsigned char *d = input; - int i, count; +static inline int ansi_c_sequences_decode_inplace(std::string &value) { + auto d = reinterpret_cast(value.data()); + const unsigned char* input = d; + const auto input_len = value.length(); - i = count = 0; + bool changed = false; + std::string::size_type i = 0; while (i < input_len) { if ((input[i] == '\\') && (i + 1 < input_len)) { int c = -1; @@ -109,43 +110,29 @@ int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, if (c == -1) { /* Didn't recognise encoding, copy raw bytes. */ *d++ = input[i + 1]; - count++; i += 2; } else { /* Converted the encoding. */ *d++ = c; - count++; } + + changed = true; } else { /* Input character not a backslash, copy it. */ *d++ = input[i++]; - count++; } } *d = '\0'; - return count; -} - - -bool EscapeSeqDecode::transform(std::string &value, const Transaction *trans) const { - - unsigned char *tmp = (unsigned char *) malloc(sizeof(char) - * value.size() + 1); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int size = ansi_c_sequences_decode_inplace(tmp, value.size()); - - std::string ret(""); - ret.assign(reinterpret_cast(tmp), size); - free(tmp); - - const auto changed = ret != value; - value = ret; + value.resize(d - input); return changed; } +bool EscapeSeqDecode::transform(std::string &value, const Transaction *trans) const { + return ansi_c_sequences_decode_inplace(value); +} + + } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/escape_seq_decode.h b/src/actions/transformations/escape_seq_decode.h index ab66464d..6a240715 100644 --- a/src/actions/transformations/escape_seq_decode.h +++ b/src/actions/transformations/escape_seq_decode.h @@ -25,7 +25,6 @@ class EscapeSeqDecode : public Transformation { explicit EscapeSeqDecode(const std::string &action); bool transform(std::string &value, const Transaction *trans) const override; - static int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); }; } // namespace modsecurity::actions::transformations From 7d5c9faa43252b6369db53691462d41b4e1f1ab4 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 08:32:27 -0700 Subject: [PATCH 62/75] Perform JsDecode transformation in-place - Removed inplace helper function from the class, as it's only referenced by the implementation. --- src/actions/transformations/js_decode.cc | 52 ++++++++---------------- src/actions/transformations/js_decode.h | 1 - 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/src/actions/transformations/js_decode.cc b/src/actions/transformations/js_decode.cc index 5ed57157..394a2cdc 100644 --- a/src/actions/transformations/js_decode.cc +++ b/src/actions/transformations/js_decode.cc @@ -21,35 +21,13 @@ namespace modsecurity::actions::transformations { -bool JsDecode::transform(std::string &value, const Transaction *trans) const { - std::string ret; - unsigned char *input; +static inline int inplace(std::string &value) { + auto d = reinterpret_cast(value.data()); + const unsigned char *input = d; + const auto input_len = value.length(); - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), i); - free(input); - - const auto changed = ret != value; - value = ret; - return changed; -} - - -int JsDecode::inplace(unsigned char *input, uint64_t input_len) { - unsigned char *d = (unsigned char *)input; - int64_t i, count; - - i = count = 0; + bool changed = false; + std::string::size_type i = 0; while (i < input_len) { if (input[i] == '\\') { /* Character is an escape. */ @@ -70,14 +48,14 @@ int JsDecode::inplace(unsigned char *input, uint64_t input_len) { } d++; - count++; i += 6; + changed = true; } else if ((i + 3 < input_len) && (input[i + 1] == 'x') && VALID_HEX(input[i + 2]) && VALID_HEX(input[i + 3])) { /* \xHH */ *d++ = utils::string::x2c(&input[i + 2]); - count++; i += 4; + changed = true; } else if ((i + 1 < input_len) && ISODIGIT(input[i + 1])) { /* \OOO (only one byte, \000 - \377) */ char buf[4]; @@ -98,7 +76,7 @@ int JsDecode::inplace(unsigned char *input, uint64_t input_len) { } *d++ = (unsigned char)strtol(buf, NULL, 8); i += 1 + j; - count++; + changed = true; } } else if (i + 1 < input_len) { /* \C */ @@ -132,23 +110,27 @@ int JsDecode::inplace(unsigned char *input, uint64_t input_len) { *d++ = c; i += 2; - count++; + changed = true; } else { /* Not enough bytes */ while (i < input_len) { *d++ = input[i++]; - count++; } } } else { *d++ = input[i++]; - count++; } } *d = '\0'; - return count; + value.resize(d - input); + return changed; +} + + +bool JsDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); } diff --git a/src/actions/transformations/js_decode.h b/src/actions/transformations/js_decode.h index b91ab9b8..94156426 100644 --- a/src/actions/transformations/js_decode.h +++ b/src/actions/transformations/js_decode.h @@ -26,7 +26,6 @@ class JsDecode : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - static int inplace(unsigned char *input, uint64_t input_len); }; } // namespace modsecurity::actions::transformations From 8bf4d96e6b3604860586251f098ba5ade3f9b67d Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 09:04:42 -0700 Subject: [PATCH 63/75] Perform HtmlEntityDecode transformation in-place - Removed inplace helper function from the class, as it's only referenced by the implementation. --- .../transformations/html_entity_decode.cc | 106 +++++++----------- .../transformations/html_entity_decode.h | 2 - 2 files changed, 38 insertions(+), 70 deletions(-) diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index a730f160..0b9d811b 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -27,47 +27,21 @@ namespace modsecurity::actions::transformations { -bool HtmlEntityDecode::transform(std::string &value, const Transaction *trans) const { - std::string ret; - unsigned char *input; +static inline bool inplace(std::string &value) { + const auto input_len = value.length(); + auto d = reinterpret_cast(value.data()); + const unsigned char *input = d; + const unsigned char *end = input + input_len; - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), i); - free(input); - - const auto changed = ret != value; - value = ret; - return changed; -} - - -int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { - unsigned char *d = input; - int i, count; - - if ((input == NULL) || (input_len == 0)) { - return 0; - } - - i = count = 0; - while ((i < input_len) && (count < input_len)) { - int z, copy = 1; + std::string::size_type i = 0; + while (i < input_len) { + std::string::size_type copy = 1; /* Require an ampersand and at least one character to * start looking into the entity. */ if ((input[i] == '&') && (i + 1 < input_len)) { - int k, j = i + 1; + auto j = i + 1; if (input[j] == '#') { /* Numerical entity. */ @@ -87,19 +61,18 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { } j++; /* j is the position of the first digit now. */ - k = j; - while ((j < input_len) && (isxdigit(input[j]))) { + constexpr int MAX_HEX_DIGITS = 2; // supports only bytes (max value 0xff) + auto k = j; + while ((j - k < MAX_HEX_DIGITS) && (j < input_len) && (isxdigit(input[j]))) { j++; } if (j > k) { /* Do we have at least one digit? */ /* Decode the entity. */ - char *x; - x = reinterpret_cast(calloc(sizeof(char), - ((j - k) + 1))); + char x[MAX_HEX_DIGITS + 1]; memcpy(x, (const char *)&input[k], j - k); - *d++ = (unsigned char)strtol(x, NULL, 16); - free(x); - count++; + x[j - k] = '\0'; + + *d++ = (unsigned char)strtol(x, nullptr, 16); /* Skip over the semicolon if it's there. */ if ((j < input_len) && (input[j] == ';')) { @@ -113,19 +86,18 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { } } else { /* Decimal entity. */ - k = j; - while ((j < input_len) && (isdigit(input[j]))) { + constexpr int MAX_DEC_DIGITS = 3; // supports only bytes (max value 255) + auto k = j; + while ((j - k < MAX_DEC_DIGITS) && (j < input_len) && (isdigit(input[j]))) { j++; } if (j > k) { /* Do we have at least one digit? */ /* Decode the entity. */ - char *x; - x = reinterpret_cast(calloc(sizeof(char), - ((j - k) + 1))); + char x[MAX_DEC_DIGITS + 1]; memcpy(x, (const char *)&input[k], j - k); - *d++ = (unsigned char)strtol(x, NULL, 10); - free(x); - count++; + x[j - k] = '\0'; + + *d++ = (unsigned char)strtol(x, nullptr, 10); /* Skip over the semicolon if it's there. */ if ((j < input_len) && (input[j] == ';')) { @@ -140,38 +112,31 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { } } else { /* Text entity. */ - k = j; + auto k = j; while ((j < input_len) && (isalnum(input[j]))) { j++; } if (j > k) { /* Do we have at least one digit? */ - char *x; - x = reinterpret_cast(calloc(sizeof(char), - ((j - k) + 1))); - memcpy(x, (const char *)&input[k], j - k); + const auto x = reinterpret_cast(&input[k]); /* Decode the entity. */ /* ENH What about others? */ - if (strcasecmp(x, "quot") == 0) { + if (strncasecmp(x, "quot", 4) == 0) { *d++ = '"'; - } else if (strcasecmp(x, "amp") == 0) { + } else if (strncasecmp(x, "amp", 3) == 0) { *d++ = '&'; - } else if (strcasecmp(x, "lt") == 0) { + } else if (strncasecmp(x, "lt", 2) == 0) { *d++ = '<'; - } else if (strcasecmp(x, "gt") == 0) { + } else if (strncasecmp(x, "gt", 2) == 0) { *d++ = '>'; - } else if (strcasecmp(x, "nbsp") == 0) { + } else if (strncasecmp(x, "nbsp", 4) == 0) { *d++ = NBSP; } else { /* We do no want to convert this entity, * copy the raw data over. */ copy = j - k + 1; - free(x); goto HTML_ENT_OUT; } - free(x); - - count++; /* Skip over the semicolon if it's there. */ if ((j < input_len) && (input[j] == ';')) { @@ -187,15 +152,20 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { HTML_ENT_OUT: - for (z = 0; ((z < copy) && (count < input_len)); z++) { + for (auto z = 0; z < copy; z++) { *d++ = input[i++]; - count++; } } *d = '\0'; - return count; + value.resize(d - input); + return d != end; +} + + +bool HtmlEntityDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); } diff --git a/src/actions/transformations/html_entity_decode.h b/src/actions/transformations/html_entity_decode.h index 558da5b9..5c17333a 100644 --- a/src/actions/transformations/html_entity_decode.h +++ b/src/actions/transformations/html_entity_decode.h @@ -26,8 +26,6 @@ class HtmlEntityDecode : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - - static int inplace(unsigned char *input, uint64_t input_len); }; } // namespace modsecurity::actions::transformations From 17a2cbd164bbfc06c09a84ce35206db57da71c53 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 09:12:12 -0700 Subject: [PATCH 64/75] Perform UrlDecodeUni & UrlDecode transformations in-place - Use std::string in UrlEncode transformation, instead of manually memory management. This avoids an additional copy after completing encoding by just swapping the encoded value and the input. - Removed inplace helper function from the class, as it's only referenced by the implementation. --- src/actions/transformations/url_decode.cc | 25 +++----- src/actions/transformations/url_decode_uni.cc | 54 ++++++----------- src/actions/transformations/url_decode_uni.h | 2 - src/actions/transformations/url_encode.cc | 60 ++++++------------- src/actions/transformations/url_encode.h | 3 - 5 files changed, 45 insertions(+), 99 deletions(-) diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index 7e5f8767..6f231022 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -27,25 +27,16 @@ UrlDecode::UrlDecode(const std::string &action) } bool UrlDecode::transform(std::string &value, const Transaction *trans) const { - unsigned char *val(NULL); int invalid_count = 0; - int _changed; + int changed; + const auto new_len = utils::urldecode_nonstrict_inplace( + (unsigned char*)value.data(), + value.length(), + &invalid_count, + &changed); - val = (unsigned char *) malloc(sizeof(char) * value.size() + 1); - memcpy(val, value.c_str(), value.size() + 1); - val[value.size()] = '\0'; - - int size = utils::urldecode_nonstrict_inplace(val, value.size(), - &invalid_count, &_changed); - std::string out; - - out.append((const char *)val, size); - - free(val); - - const auto changed = out != value; - value = out; - return changed; + value.resize(new_len); + return changed != 0; } diff --git a/src/actions/transformations/url_decode_uni.cc b/src/actions/transformations/url_decode_uni.cc index fdc2e79b..57df7a56 100644 --- a/src/actions/transformations/url_decode_uni.cc +++ b/src/actions/transformations/url_decode_uni.cc @@ -22,41 +22,19 @@ namespace modsecurity::actions::transformations { -bool UrlDecodeUni::transform(std::string &value, const Transaction *t) const { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length(), t); - - ret.assign(reinterpret_cast(input), i); - free(input); - - const auto changed = ret != value; - value = ret; - return changed; -} - - /** * * IMP1 Assumes NUL-terminated */ -int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, +static inline bool inplace(std::string &value, const Transaction *t) { - unsigned char *d = input; - int64_t i, count, fact, j, xv; - int Code, hmap = -1; + bool changed = false; + auto d = reinterpret_cast(value.data()); + const unsigned char *input = d; + const auto input_len = value.length(); - if (input == NULL) return -1; + std::string::size_type i, count, fact, j, xv; + int Code, hmap = -1; i = count = 0; while (i < input_len) { @@ -116,19 +94,17 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, } } d++; - count++; i += 6; + changed = true; } else { /* Invalid data, skip %u. */ *d++ = input[i++]; *d++ = input[i++]; - count += 2; } } else { /* Not enough bytes (4 data bytes), skip %u. */ *d++ = input[i++]; *d++ = input[i++]; - count += 2; } } else { /* Standard URL encoding. */ @@ -143,8 +119,8 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, if (VALID_HEX(c1) && VALID_HEX(c2)) { *d++ = utils::string::x2c(&input[i + 1]); - count++; i += 3; + changed = true; } else { /* Not a valid encoding, skip this % */ *d++ = input[i++]; @@ -153,25 +129,31 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, } else { /* Not enough bytes available, skip this % */ *d++ = input[i++]; - count++; } } } else { /* Character is not a percent sign. */ if (input[i] == '+') { *d++ = ' '; + changed = true; } else { *d++ = input[i]; } - count++; i++; } } *d = '\0'; - return count; + value.resize(d - input); + return changed; +} + + + +bool UrlDecodeUni::transform(std::string &value, const Transaction *trans) const { + return inplace(value, trans); } diff --git a/src/actions/transformations/url_decode_uni.h b/src/actions/transformations/url_decode_uni.h index 31962851..8dbac462 100644 --- a/src/actions/transformations/url_decode_uni.h +++ b/src/actions/transformations/url_decode_uni.h @@ -26,8 +26,6 @@ class UrlDecodeUni : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - static int inplace(unsigned char *input, uint64_t input_len, - const Transaction *transaction); }; } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_encode.cc b/src/actions/transformations/url_encode.cc index e7f59f85..36fef771 100644 --- a/src/actions/transformations/url_encode.cc +++ b/src/actions/transformations/url_encode.cc @@ -26,65 +26,43 @@ UrlEncode::UrlEncode(const std::string &action) } -std::string UrlEncode::url_enc(const char *input, - unsigned int input_len, int *changed) { - char *rval, *d; - unsigned int i, len; - int count = 0; +static inline bool url_enc(std::string &value) { + const auto len = value.size() * 3 + 1; + std::string ret(len, {}); - *changed = 0; - - len = input_len * 3 + 1; - d = rval = reinterpret_cast(malloc(len)); - if (rval == NULL) { - return {}; - } + bool changed = false; /* ENH Only encode the characters that really need to be encoded. */ - for (i = 0; i < input_len; i++) { - unsigned char c = input[i]; - + char *d = ret.data(); + for (const auto c : value) { if (c == ' ') { *d++ = '+'; - *changed = 1; - count++; + changed = true; } else { if ( (c == 42) || ((c >= 48) && (c <= 57)) || ((c >= 65) && (c <= 90)) || ((c >= 97) && (c <= 122))) { *d++ = c; - count++; - } else { + } + else + { *d++ = '%'; - count++; - utils::string::c2x(c, (unsigned char *)d); - d += 2; - count++; - count++; - *changed = 1; + d = (char *)utils::string::c2x(c, (unsigned char *)d); + changed = true; } } } - *d = '\0'; - - std::string ret(""); - ret.append(rval, count); - free(rval); - return ret; -} - - -bool UrlEncode::transform(std::string &value, const Transaction *trans) const { - int _changed; - - std::string ret = url_enc(value.c_str(), value.size(), &_changed); - - const auto changed = ret != value; - value = ret; + ret.resize(d - ret.c_str()); + std::swap(value, ret); return changed; } +bool UrlEncode::transform(std::string &value, const Transaction *trans) const { + return url_enc(value); +} + + } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_encode.h b/src/actions/transformations/url_encode.h index b300c40d..4f3ffe73 100644 --- a/src/actions/transformations/url_encode.h +++ b/src/actions/transformations/url_encode.h @@ -25,9 +25,6 @@ class UrlEncode : public Transformation { explicit UrlEncode(const std::string &action); bool transform(std::string &value, const Transaction *trans) const override; - - static std::string url_enc(const char *input, - unsigned int input_len, int *changed); }; } // namespace modsecurity::actions::transformations From 2c3c2287259b68206141efb6bc270ddd83727654 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 10:15:12 -0700 Subject: [PATCH 65/75] Perform Utf8ToUnicode transformation in-place - Removed inplace helper function from the class, as it's only referenced by the implementation. --- .../transformations/utf8_to_unicode.cc | 87 +++++++------------ src/actions/transformations/utf8_to_unicode.h | 9 -- 2 files changed, 30 insertions(+), 66 deletions(-) diff --git a/src/actions/transformations/utf8_to_unicode.cc b/src/actions/transformations/utf8_to_unicode.cc index 2f40ce60..4b01583e 100644 --- a/src/actions/transformations/utf8_to_unicode.cc +++ b/src/actions/transformations/utf8_to_unicode.cc @@ -20,67 +20,33 @@ #include "src/utils/string.h" +constexpr int UNICODE_ERROR_CHARACTERS_MISSING = -1; +constexpr int UNICODE_ERROR_INVALID_ENCODING = -2; + + namespace modsecurity::actions::transformations { -bool Utf8ToUnicode::transform(std::string &value, const Transaction *trans) const { - std::string ret; - unsigned char *input; - int _changed = 0; - char *out; +static inline bool encode(std::string &value) { + auto input = reinterpret_cast(value.data()); + const auto input_len = value.length(); - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - out = inplace(input, value.size() + 1, &_changed); - free(input); - if (out != NULL) { - ret.assign(reinterpret_cast(out), - strlen(reinterpret_cast(out))); - free(out); - } - - const auto changed = ret != value; - value = ret; - return changed; -} - - -char *Utf8ToUnicode::inplace(unsigned char *input, - uint64_t input_len, int *changed) { - unsigned int count = 0; - char *data; - char *data_orig; - unsigned int i, len, j; - unsigned int bytes_left = input_len; + bool changed = false; + std::string::size_type count = 0; + auto bytes_left = input_len; unsigned char unicode[8]; - *changed = 0; /* RFC3629 states that UTF-8 are encoded using sequences of 1 to 4 octets. */ /* Max size per character should fit in 4 bytes */ - len = input_len * 4 + 1; - data = reinterpret_cast(malloc(sizeof(char) * len)); - if (data == NULL) { - return NULL; - } - data_orig = data; + const auto len = input_len * 4 + 1; + std::string ret(len, {}); + auto data = ret.data(); - if (input == NULL) { - free(data); - return NULL; - } - - for (i = 0; i < bytes_left;) { + for (std::string::size_type i = 0; i < bytes_left;) { int unicode_len = 0; unsigned int d = 0; unsigned char c; - unsigned char *utf = (unsigned char *)&input[i]; + auto utf = &input[i]; c = *utf; @@ -108,7 +74,7 @@ char *Utf8ToUnicode::inplace(unsigned char *input, unicode_len = UNICODE_ERROR_INVALID_ENCODING; } else { unicode_len = 2; - count+=6; + count += 6; if (count <= len) { int length = 0; /* compute character number */ @@ -138,11 +104,11 @@ char *Utf8ToUnicode::inplace(unsigned char *input, break; } - for (j = 0; j < length; j++) { + for (std::string::size_type j = 0; j < length; j++) { *data++ = unicode[j]; } - *changed = 1; + changed = true; } } } else if ((c & 0xF0) == 0xE0) { @@ -190,11 +156,11 @@ char *Utf8ToUnicode::inplace(unsigned char *input, break; } - for (j = 0; j < length; j++) { + for (std::string::size_type j = 0; j < length; j++) { *data++ = unicode[j]; } - *changed = 1; + changed = true; } } } else if ((c & 0xF8) == 0xF0) { @@ -252,11 +218,11 @@ char *Utf8ToUnicode::inplace(unsigned char *input, break; } - for (j = 0; j < length; j++) { + for (std::string::size_type j = 0; j < length; j++) { *data++ = unicode[j]; } - *changed = 1; + changed = true; } } } else { @@ -300,7 +266,14 @@ char *Utf8ToUnicode::inplace(unsigned char *input, *data ='\0'; - return data_orig; + ret.resize(data - ret.c_str()); + std::swap(value, ret); + return changed; +} + + +bool Utf8ToUnicode::transform(std::string &value, const Transaction *trans) const { + return encode(value); } diff --git a/src/actions/transformations/utf8_to_unicode.h b/src/actions/transformations/utf8_to_unicode.h index 83aba819..bbb6cdc4 100644 --- a/src/actions/transformations/utf8_to_unicode.h +++ b/src/actions/transformations/utf8_to_unicode.h @@ -18,12 +18,6 @@ #include "transformation.h" -#define UNICODE_ERROR_CHARACTERS_MISSING -1 -#define UNICODE_ERROR_INVALID_ENCODING -2 -#define UNICODE_ERROR_OVERLONG_CHARACTER -3 -#define UNICODE_ERROR_RESTRICTED_CHARACTER -4 -#define UNICODE_ERROR_DECODING_ERROR -5 - namespace modsecurity::actions::transformations { class Utf8ToUnicode : public Transformation { @@ -32,9 +26,6 @@ class Utf8ToUnicode : public Transformation { : Transformation(action) { } bool transform(std::string &value, const Transaction *trans) const override; - - static char *inplace(unsigned char *input, uint64_t input_len, - int *changed); }; } // namespace modsecurity::actions::transformations From 021d0caa335637b493b9a1e45e2273c64659694f Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 10:20:12 -0700 Subject: [PATCH 66/75] Perform NormalisePath & NormalisePathWin transformations in-place --- src/actions/transformations/normalise_path.cc | 60 +++++++------------ src/actions/transformations/normalise_path.h | 3 +- .../transformations/normalise_path_win.cc | 19 +----- 3 files changed, 24 insertions(+), 58 deletions(-) diff --git a/src/actions/transformations/normalise_path.cc b/src/actions/transformations/normalise_path.cc index c663b98a..dd2b64d2 100644 --- a/src/actions/transformations/normalise_path.cc +++ b/src/actions/transformations/normalise_path.cc @@ -25,23 +25,7 @@ NormalisePath::NormalisePath(const std::string &action) } bool NormalisePath::transform(std::string &value, const Transaction *trans) const { - int _changed = 0; - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int i = normalize_path_inplace((unsigned char *)tmp, - value.size(), 0, &_changed); - - std::string ret(""); - ret.assign(tmp, i); - free(tmp); - - const auto changed = ret != value; - value = ret; - return changed; + return normalize_path_inplace(value, false); } @@ -49,21 +33,22 @@ bool NormalisePath::transform(std::string &value, const Transaction *trans) cons * * IMP1 Assumes NUL-terminated */ -int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, - int win, int *changed) { +bool NormalisePath::normalize_path_inplace(std::string &val, const bool win) { unsigned char *src; unsigned char *dst; unsigned char *end; - int ldst = 0; int hitroot = 0; int done = 0; int relative; int trailing; - *changed = 0; + bool changed = false; /* Need at least one byte to normalize */ - if (input_len <= 0) return 0; + if(val.empty()) return false; + + auto input = reinterpret_cast(val.data()); + const auto input_len = val.length(); /* * ENH: Deal with UNC and drive letters? @@ -71,7 +56,6 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, src = dst = input; end = input + (input_len - 1); - ldst = 1; relative = ((*input == '/') || (win && (*input == '\\'))) ? 0 : 1; trailing = ((*end == '/') || (win && (*end == '\\'))) ? 1 : 0; @@ -82,11 +66,11 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, if (win) { if (*src == '\\') { *src = '/'; - *changed = 1; + changed = true; } if ((src < end) && (*(src + 1) == '\\')) { *(src + 1) = '/'; - *changed = 1; + changed = true; } } @@ -104,7 +88,7 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, /* Could it be an empty path segment? */ if ((src != end) && *src == '/') { /* Ignore */ - *changed = 1; + changed = true; goto copy; /* Copy will take care of this. */ } else if (*src == '.') { /* Could it be a back or self reference? */ @@ -141,25 +125,25 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, } } - if (done) goto length; /* Skip the copy. */ + if (done) goto skip_copy; /* Skip the copy. */ src++; - *changed = 1; + changed = true; } else if (dst == input) { /* Relative Self-reference? */ - *changed = 1; + changed = true; /* Ignore. */ - if (done) goto length; /* Skip the copy. */ + if (done) goto skip_copy; /* Skip the copy. */ src++; } else if (*(dst - 1) == '/') { /* Self-reference? */ - *changed = 1; + changed = true; /* Ignore. */ - if (done) goto length; /* Skip the copy. */ + if (done) goto skip_copy; /* Skip the copy. */ dst--; src++; } @@ -179,7 +163,7 @@ copy: && ((*(src + 1) == '/') || (win && (*(src + 1) == '\\'))) ) { src++; } - if (oldsrc != src) *changed = 1; + if (oldsrc != src) changed = true; /* Do not copy the forward slash to the root * if it is not a relative path. Instead @@ -187,27 +171,27 @@ copy: */ if (relative && (dst == input)) { src++; - goto length; /* Skip the copy */ + goto skip_copy; /* Skip the copy */ } } *(dst++) = *(src++); -length: - ldst = (dst - input); +skip_copy: + ; // nop for the goto label to work } /* Make sure that there is not a trailing slash in the * normalized form if there was not one in the original form. */ if (!trailing && (dst > input) && *(dst - 1) == '/') { - ldst--; dst--; } /* Always NUL terminate */ *dst = '\0'; - return ldst; + val.resize(dst - input); + return changed; } diff --git a/src/actions/transformations/normalise_path.h b/src/actions/transformations/normalise_path.h index d5b84085..248def7f 100644 --- a/src/actions/transformations/normalise_path.h +++ b/src/actions/transformations/normalise_path.h @@ -26,8 +26,7 @@ class NormalisePath : public Transformation { bool transform(std::string &value, const Transaction *trans) const override; - static int normalize_path_inplace(unsigned char *input, int input_len, - int win, int *changed); + static bool normalize_path_inplace(std::string &val, const bool win); }; } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/normalise_path_win.cc b/src/actions/transformations/normalise_path_win.cc index 49f6989f..b60943e1 100644 --- a/src/actions/transformations/normalise_path_win.cc +++ b/src/actions/transformations/normalise_path_win.cc @@ -22,24 +22,7 @@ namespace modsecurity::actions::transformations { bool NormalisePathWin::transform(std::string &value, const Transaction *trans) const { - int _changed; - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int i = NormalisePath::normalize_path_inplace( - reinterpret_cast(tmp), - value.size(), 1, &_changed); - - std::string ret(""); - ret.assign(tmp, i); - free(tmp); - - const auto changed = ret != value; - value = ret; - return changed; + return NormalisePath::normalize_path_inplace(value, true); } From b647dbd905302cf85f7eb8d6e83813229ef8dc58 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Sat, 1 Jun 2024 21:59:16 +0000 Subject: [PATCH 67/75] Remove unnecessary heap-allocation & copy in Transaction::extractArguments - utils::urldecode_nonstrict_inplace decodes inplace so key & value, which are values returned by utils::string::ssplit_pair can be just be modified and do not need to be copied. - Updated signature of utils::urldecode_nonstrict_inplace, as its two callers already have std::string values. --- src/actions/transformations/url_decode.cc | 12 +---- src/transaction.cc | 42 ++++----------- src/utils/decode.cc | 62 ++++++++++------------- src/utils/decode.h | 4 +- 4 files changed, 40 insertions(+), 80 deletions(-) diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index 6f231022..c67e9fa6 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -27,16 +27,8 @@ UrlDecode::UrlDecode(const std::string &action) } bool UrlDecode::transform(std::string &value, const Transaction *trans) const { - int invalid_count = 0; - int changed; - const auto new_len = utils::urldecode_nonstrict_inplace( - (unsigned char*)value.data(), - value.length(), - &invalid_count, - &changed); - - value.resize(new_len); - return changed != 0; + int invalid_count; + return utils::urldecode_nonstrict_inplace(value, invalid_count); } diff --git a/src/transaction.cc b/src/transaction.cc index f69df188..8c9dd669 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -348,46 +348,22 @@ bool Transaction::extractArguments(const std::string &orig, if (m_rules->m_secArgumentSeparator.m_set) { sep1 = m_rules->m_secArgumentSeparator.m_value.at(0); } - std::vector key_value_sets = utils::string::ssplit(buf, sep1); + const auto key_value_sets = utils::string::ssplit(buf, sep1); - for (std::string t : key_value_sets) { - char sep2 = '='; - size_t key_s = 0; - size_t value_s = 0; - int invalid = 0; - int changed = 0; + for (const auto &t : key_value_sets) { + const auto sep2 = '='; + auto [key, value] = utils::string::ssplit_pair(t, sep2); - std::string key; - std::string value; - std::pair key_value_pair = utils::string::ssplit_pair(t, sep2); - key = key_value_pair.first; - value = key_value_pair.second; + int invalid_count; + utils::urldecode_nonstrict_inplace(key, invalid_count); + utils::urldecode_nonstrict_inplace(value, invalid_count); - key_s = (key.length() + 1); - value_s = (value.length() + 1); - unsigned char *key_c = reinterpret_cast( - calloc(sizeof(char), key_s)); - unsigned char *value_c = reinterpret_cast( - calloc(sizeof(char), value_s)); - - memcpy(key_c, key.c_str(), key_s); - memcpy(value_c, value.c_str(), value_s); - - key_s = utils::urldecode_nonstrict_inplace(key_c, key_s, - &invalid, &changed); - value_s = utils::urldecode_nonstrict_inplace(value_c, value_s, - &invalid, &changed); - - if (invalid) { + if (invalid_count > 0) { m_variableUrlEncodedError.set("1", m_variableOffset); } - addArgument(orig, std::string(reinterpret_cast(key_c), key_s-1), - std::string(reinterpret_cast(value_c), value_s-1), offset); + addArgument(orig, key, value, offset); offset = offset + t.size() + 1; - - free(key_c); - free(value_c); } return true; diff --git a/src/utils/decode.cc b/src/utils/decode.cc index 8629f8fb..32d95301 100644 --- a/src/utils/decode.cc +++ b/src/utils/decode.cc @@ -22,63 +22,55 @@ namespace modsecurity { namespace utils { -int urldecode_nonstrict_inplace(unsigned char *input, - uint64_t input_len, int *invalid_count, int *changed) { - unsigned char *d = (unsigned char *)input; - uint64_t i, count; +bool urldecode_nonstrict_inplace(std::string &val, + int &invalid_count) { + unsigned char *d = (unsigned char *)val.data(); + unsigned char *s = d; + const unsigned char *e = s + val.size(); - *changed = 0; + invalid_count = 0; + bool changed = false; - if (input == NULL) { - return -1; - } - - i = count = 0; - while (i < input_len) { - if (input[i] == '%') { + while (s != e) { + if (*s == '%') { /* Character is a percent sign. */ /* Are there enough bytes available? */ - if (i + 2 < input_len) { - char c1 = input[i + 1]; - char c2 = input[i + 2]; + if (s + 2 < e) { + const auto c1 = *(s + 1); + const auto c2 = *(s + 2); if (VALID_HEX(c1) && VALID_HEX(c2)) { - uint64_t uni = string::x2c(&input[i + 1]); + const auto uni = string::x2c(s + 1); - *d++ = (wchar_t)uni; - count++; - i += 3; - *changed = 1; + *d++ = uni; + s += 3; + changed = true; } else { /* Not a valid encoding, skip this % */ - *d++ = input[i++]; - count++; - (*invalid_count)++; + *d++ = *s++; + invalid_count++; } } else { /* Not enough bytes available, copy the raw bytes. */ - *d++ = input[i++]; - count++; - (*invalid_count)++; + *d++ = *s++; + invalid_count++; } } else { /* Character is not a percent sign. */ - if (input[i] == '+') { + if (*s == '+') { *d++ = ' '; - *changed = 1; + changed = true; } else { - *d++ = input[i]; + *d++ = *s; } - count++; - i++; + s++; } } -#if 0 - *d = '\0'; -#endif + if (changed) + val.resize((char*) d - val.c_str()); - return count; + return changed; } diff --git a/src/utils/decode.h b/src/utils/decode.h index e0e31bcb..d80a55d5 100644 --- a/src/utils/decode.h +++ b/src/utils/decode.h @@ -29,8 +29,8 @@ namespace modsecurity { namespace utils { -int urldecode_nonstrict_inplace(unsigned char *input, - uint64_t input_len, int *invalid_count, int *changed); +bool urldecode_nonstrict_inplace(std::string &val, + int &invalid_count); std::string uri_decode(const std::string & sSrc); From 34da8eeeee3f3272c7e8e0b8846ef7d1e7f4e47e Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 9 Aug 2024 13:03:34 -0700 Subject: [PATCH 68/75] Pass RuleWithActions::executeTransformation arguments by reference - This function already expects these arguments not to be null pointers, doesn't validate them and just dereference them. - In order to make this explicit and enforced by the compiler, they're now passed as references. --- headers/modsecurity/rule_with_actions.h | 6 ++--- src/rule_with_actions.cc | 30 ++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/headers/modsecurity/rule_with_actions.h b/headers/modsecurity/rule_with_actions.h index bb63f499..26967f2a 100644 --- a/headers/modsecurity/rule_with_actions.h +++ b/headers/modsecurity/rule_with_actions.h @@ -161,9 +161,9 @@ class RuleWithActions : public Rule { const actions::transformations::Transformation &a, std::string &value, const Transaction *trans, - TransformationResults *ret, - std::string *path, - int *nth) const; + TransformationResults &ret, + std::string &path, + int &nth) const; /* actions */ actions::Action *m_disruptiveAction; diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index 1b76005c..7aa0e649 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -327,24 +327,24 @@ inline void RuleWithActions::executeTransformation( const actions::transformations::Transformation &a, std::string &value, const Transaction *trans, - TransformationResults *ret, - std::string *path, - int *nth) const { + TransformationResults &ret, + std::string &path, + int &nth) const { if (a.transform(value, trans) && m_containsMultiMatchAction) { ret.emplace_back(value, a.m_name); - (*nth)++; + nth++; } - if (path->empty()) { - path->append(*a.m_name.get()); + if (path.empty()) { + path.append(*a.m_name.get()); } else { - path->append("," + *a.m_name.get()); + path.append("," + *a.m_name.get()); } ms_dbg_a(trans, 9, " T (" + \ - std::to_string(*nth) + ") " + \ + std::to_string(nth) + ") " + \ *a.m_name.get() + ": \"" + \ utils::string::limitTo(80, value) +"\""); } @@ -353,7 +353,7 @@ void RuleWithActions::executeTransformations( const Transaction *trans, const std::string &in, TransformationResults &ret) { int none = 0; int transformations = 0; - std::string path(""); + std::string path; auto value = in; if (m_containsMultiMatchAction == true) { @@ -381,16 +381,16 @@ void RuleWithActions::executeTransformations( // FIXME: here the object needs to be a transformation already. auto t = dynamic_cast(a.get()); assert(t != nullptr); - executeTransformation(*t, value, trans, &ret, &path, - &transformations); + executeTransformation(*t, value, trans, ret, path, + transformations); } } for (const Transformation *a : m_transformations) { assert(a != nullptr); if (none == 0) { - executeTransformation(*a, value, trans, &ret, &path, - &transformations); + executeTransformation(*a, value, trans, ret, path, + transformations); } if (a->m_isNone) { none--; @@ -419,8 +419,8 @@ void RuleWithActions::executeTransformations( auto a = dynamic_cast(b.second.get()); assert(a != nullptr); if (none == 0) { - executeTransformation(*a, value, trans, &ret, &path, - &transformations); + executeTransformation(*a, value, trans, ret, path, + transformations); } if (a->m_isNone) { none--; From fedec96a7ec21c2f9cc7fa1c0e36d2033d563316 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 10:25:36 -0700 Subject: [PATCH 69/75] Refactored base64 utils to share implementation and reduce code duplication. --- src/utils/base64.cc | 87 +++++++++++---------------------------------- 1 file changed, 21 insertions(+), 66 deletions(-) diff --git a/src/utils/base64.cc b/src/utils/base64.cc index ebbb7393..7b1f4b07 100644 --- a/src/utils/base64.cc +++ b/src/utils/base64.cc @@ -23,33 +23,30 @@ #include "mbedtls/base64.h" +template +inline std::string base64Helper(const char *data, const unsigned int len, Operation op) { + size_t out_len = 0; + + op(nullptr, 0, &out_len, + reinterpret_cast(data), len); + + std::string ret(out_len, {}); + if(out_len > 0) { + op(reinterpret_cast(ret.data()), ret.size(), &out_len, + reinterpret_cast(data), len); + + ret.resize(out_len); + } + + return ret; +} + namespace modsecurity { namespace Utils { std::string Base64::encode(const std::string& data) { - size_t encoded_len = 0; - unsigned char *d; - std::string ret; - - mbedtls_base64_encode(NULL, 0, &encoded_len, - reinterpret_cast(data.c_str()), data.size()); - - d = reinterpret_cast(malloc(sizeof(char) * encoded_len)); - if (d == NULL) { - return data; - } - - memset(d, '\0', encoded_len); - - mbedtls_base64_encode(d, encoded_len, &encoded_len, - (unsigned char*) data.c_str(), data.size()); - - ret.assign(reinterpret_cast(d), encoded_len); - free(d); - - - return ret; + return base64Helper(data.c_str(), data.size(), mbedtls_base64_encode); } @@ -63,53 +60,12 @@ std::string Base64::decode(const std::string& data, bool forgiven) { std::string Base64::decode(const std::string& data) { - size_t decoded_len = 0; - unsigned char *d; - std::string ret; - size_t len = strlen(data.c_str()); - - mbedtls_base64_decode(NULL, 0, &decoded_len, - reinterpret_cast(data.c_str()), len); - - d = reinterpret_cast(malloc(sizeof(char) * decoded_len)); - if (d == NULL) { - return data; - } - - memset(d, '\0', decoded_len); - - mbedtls_base64_decode(d, decoded_len, &decoded_len, - reinterpret_cast(data.c_str()), len); - - ret.assign(reinterpret_cast(d), decoded_len); - free(d); - - return ret; + return base64Helper(data.c_str(), strlen(data.c_str()), mbedtls_base64_decode); } std::string Base64::decode_forgiven(const std::string& data) { - size_t decoded_len = 0; - unsigned char *d; - std::string ret; - - decode_forgiven_engine(NULL, 0, &decoded_len, - reinterpret_cast(data.c_str()), data.size()); - - d = reinterpret_cast(malloc(sizeof(char) * decoded_len)); - if (d == NULL) { - return data; - } - - memset(d, '\0', decoded_len); - - decode_forgiven_engine(d, decoded_len, &decoded_len, - reinterpret_cast(data.c_str()), data.size()); - - ret.assign(reinterpret_cast(d), decoded_len); - free(d); - - return ret; + return base64Helper(data.c_str(), data.size(), decode_forgiven_engine); } @@ -215,6 +171,5 @@ void Base64::decode_forgiven_engine(unsigned char *plain_text, } } - } // namespace Utils } // namespace modsecurity From 7023c0a8b4850e020837dcc00539715f943992a5 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 10:34:00 -0700 Subject: [PATCH 70/75] Refactored sha1 & md5 utils to share implementation and reduce code duplication. --- src/Makefile.am | 2 -- src/utils/md5.cc | 40 ------------------------------- src/utils/md5.h | 23 ++++++------------ src/utils/sha1.cc | 60 ----------------------------------------------- src/utils/sha1.h | 59 +++++++++++++++++++++++++++++++++++++--------- 5 files changed, 55 insertions(+), 129 deletions(-) delete mode 100644 src/utils/md5.cc delete mode 100644 src/utils/sha1.cc diff --git a/src/Makefile.am b/src/Makefile.am index 6f358655..2a32b97b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -248,11 +248,9 @@ UTILS = \ utils/geo_lookup.cc \ utils/https_client.cc \ utils/ip_tree.cc \ - utils/md5.cc \ utils/msc_tree.cc \ utils/random.cc \ utils/regex.cc \ - utils/sha1.cc \ utils/system.cc \ utils/shared_files.cc diff --git a/src/utils/md5.cc b/src/utils/md5.cc deleted file mode 100644 index 99b9d278..00000000 --- a/src/utils/md5.cc +++ /dev/null @@ -1,40 +0,0 @@ - - -#include "src/utils/md5.h" -#include "mbedtls/md5.h" - -namespace modsecurity { -namespace Utils { - - -std::string Md5::hexdigest(const std::string& input) { - unsigned char digest[16]; - - mbedtls_md5(reinterpret_cast(input.c_str()), - input.size(), digest); - - char buf[33]; - for (int i = 0; i < 16; i++) { - sprintf(buf+i*2, "%02x", digest[i]); - } - - return std::string(buf, 32); -} - - -std::string Md5::digest(const std::string& input) { - unsigned char output[16]; - std::string ret; - - mbedtls_md5(reinterpret_cast(input.c_str()), - input.size(), output); - - ret.assign(reinterpret_cast(output), 16); - - return ret; -} - - -} // namespace Utils -} // namespace modsecurity - diff --git a/src/utils/md5.h b/src/utils/md5.h index b6ebc120..68f5d748 100644 --- a/src/utils/md5.h +++ b/src/utils/md5.h @@ -13,29 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_UTILS_MD5_H_ #define SRC_UTILS_MD5_H_ -#include -#include +#include "src/utils/sha1.h" +#include "mbedtls/md5.h" +#include -namespace modsecurity { -namespace Utils { +namespace modsecurity::Utils { -class Md5 { - public: - Md5() { } - static std::string hexdigest(const std::string& input); - static std::string digest(const std::string& input); +class Md5 : public DigestImpl<&mbedtls_md5, 16> { }; -} // namespace Utils -} // namespace modsecurity + +} // namespace modsecurity::Utils #endif // SRC_UTILS_MD5_H_ \ No newline at end of file diff --git a/src/utils/sha1.cc b/src/utils/sha1.cc deleted file mode 100644 index 4c28d4ed..00000000 --- a/src/utils/sha1.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/) - * - * You may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * If any of the files related to licensing are missing or if you have any - * other questions related to licensing please contact Trustwave Holdings, Inc. - * directly using the email address security@modsecurity.org. - * - */ - - -#include "src/utils/sha1.h" -#include "mbedtls/sha1.h" -#include -#include -#include - -namespace modsecurity { -namespace Utils { - - -std::string Sha1::hexdigest(const std::string& input) { - unsigned char digest[20] = { 0 }; - static const char* const lut = "0123456789abcdef"; - - mbedtls_sha1(reinterpret_cast(input.c_str()), - input.size(), digest); - std::string a; - - for (int i = 0; i < 20; i++) { - const unsigned char c = digest[i]; - a.push_back(lut[c >> 4]); - a.push_back(lut[c & 15]); - } - - return a; -} - - -std::string Sha1::digest(const std::string& input) { - unsigned char output[20]; - std::string ret; - - mbedtls_sha1(reinterpret_cast(input.c_str()), - input.size(), output); - - ret.assign(reinterpret_cast(output), 20); - - return ret; -} - - -} // namespace Utils -} // namespace modsecurity - diff --git a/src/utils/sha1.h b/src/utils/sha1.h index 6bae47c2..2dac3ea2 100644 --- a/src/utils/sha1.h +++ b/src/utils/sha1.h @@ -13,26 +13,63 @@ * */ - #ifndef SRC_UTILS_SHA1_H_ #define SRC_UTILS_SHA1_H_ -#include -#include #include +#include -namespace modsecurity { -namespace Utils { +#include "src/utils/string.h" +#include "mbedtls/sha1.h" -class Sha1 { +namespace modsecurity::Utils { + + +using DigestOp = int (*)(const unsigned char *, size_t, unsigned char []); + + +template +class DigestImpl { public: - Sha1() { } - static std::string hexdigest(const std::string& input); - static std::string digest(const std::string& input); + static std::string digest(const std::string& input) { + return digestHelper(input, [](const auto digest) { + return std::string(digest); + }); + } + + static void digestReplace(std::string& value) { + digestHelper(value, [&value](const auto digest) mutable { + value = digest; + }); + } + + static std::string hexdigest(const std::string &input) { + return digestHelper(input, [](const auto digest) { + return utils::string::string_to_hex(digest); + }); + } + +private: + + template + static auto digestHelper(const std::string &input, + ConvertOp convertOp) -> auto { + char digest[DigestSize]; + + auto ret = digestOp(reinterpret_cast(input.c_str()), + input.size(), reinterpret_cast(digest)); + assert(ret == 0); + + return convertOp(std::string_view(digest, DigestSize)); + } }; -} // namespace Utils -} // namespace modsecurity + +class Sha1 : public DigestImpl<&mbedtls_sha1, 20> { +}; + + +} // namespace modsecurity::Utils #endif // SRC_UTILS_SHA1_H_ From 2f5dac5c4cbd41ecb4c07bfc01ba02effff98d62 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Mon, 19 Aug 2024 11:26:56 -0700 Subject: [PATCH 71/75] Simplified initialization of Transformation's action_kind - Some of the Transformation classes would initialize their Action's action_kind using the default (using Transformation constructor without an action_kind parameter). - Others, however, would use that constructor and initialize action_kind manually in their constructor, but setting the default value (RunTimeBeforeMatchAttemptKind = 1), which was redundant. - Removed unused Transformation constructor to specify action_kind. - Converted Action::Kind into an 'enum class' to require using the enum constants (instead of integer values, which are difficult to track in the codebase and change) --- headers/modsecurity/actions/action.h | 70 +++++++++---------- src/actions/accuracy.h | 2 +- src/actions/audit_log.h | 2 +- src/actions/capture.h | 2 +- src/actions/chain.h | 2 +- src/actions/ctl/audit_engine.h | 2 +- src/actions/ctl/audit_log_parts.h | 2 +- src/actions/ctl/request_body_access.h | 2 +- src/actions/ctl/request_body_processor_json.h | 2 +- .../ctl/request_body_processor_urlencoded.h | 2 +- src/actions/ctl/request_body_processor_xml.h | 2 +- src/actions/ctl/rule_engine.h | 2 +- src/actions/ctl/rule_remove_by_id.h | 2 +- src/actions/ctl/rule_remove_by_tag.h | 2 +- src/actions/ctl/rule_remove_target_by_id.h | 2 +- src/actions/ctl/rule_remove_target_by_tag.h | 2 +- src/actions/data/status.h | 4 +- src/actions/disruptive/allow.h | 2 +- src/actions/disruptive/redirect.h | 4 +- src/actions/expire_var.h | 2 +- src/actions/init_col.h | 2 +- src/actions/log.h | 2 +- src/actions/log_data.h | 4 +- src/actions/maturity.h | 2 +- src/actions/msg.h | 4 +- src/actions/multi_match.h | 2 +- src/actions/no_audit_log.h | 2 +- src/actions/no_log.h | 2 +- src/actions/phase.h | 2 +- src/actions/rev.h | 2 +- src/actions/rule_id.h | 2 +- src/actions/set_env.h | 2 +- src/actions/set_rsc.h | 2 +- src/actions/set_sid.h | 2 +- src/actions/set_uid.h | 2 +- src/actions/skip.h | 2 +- src/actions/skip_after.h | 2 +- src/actions/tag.h | 2 +- src/actions/transformations/base64_decode.h | 3 +- .../transformations/base64_decode_ext.h | 3 +- src/actions/transformations/base64_encode.h | 3 +- src/actions/transformations/cmd_line.h | 3 +- .../transformations/compress_whitespace.cc | 5 -- .../transformations/compress_whitespace.h | 2 +- src/actions/transformations/css_decode.h | 3 +- .../transformations/escape_seq_decode.cc | 6 -- .../transformations/escape_seq_decode.h | 2 +- src/actions/transformations/hex_decode.h | 3 +- src/actions/transformations/hex_encode.cc | 4 -- src/actions/transformations/hex_encode.h | 2 +- .../transformations/html_entity_decode.h | 3 +- src/actions/transformations/js_decode.h | 3 +- src/actions/transformations/length.cc | 5 -- src/actions/transformations/length.h | 2 +- src/actions/transformations/lower_case.cc | 4 -- src/actions/transformations/lower_case.h | 2 +- src/actions/transformations/md5.h | 3 +- src/actions/transformations/normalise_path.cc | 5 -- src/actions/transformations/normalise_path.h | 2 +- .../transformations/normalise_path_win.h | 3 +- .../transformations/parity_even_7bit.h | 3 +- src/actions/transformations/parity_odd_7bit.h | 3 +- .../transformations/parity_zero_7bit.h | 3 +- src/actions/transformations/remove_comments.h | 3 +- .../transformations/remove_comments_char.cc | 4 -- .../transformations/remove_comments_char.h | 2 +- src/actions/transformations/remove_nulls.h | 3 +- .../transformations/remove_whitespace.cc | 5 -- .../transformations/remove_whitespace.h | 2 +- .../transformations/replace_comments.cc | 6 -- .../transformations/replace_comments.h | 2 +- src/actions/transformations/replace_nulls.cc | 4 -- src/actions/transformations/replace_nulls.h | 2 +- src/actions/transformations/sha1.cc | 5 +- src/actions/transformations/sha1.h | 2 +- src/actions/transformations/sql_hex_decode.h | 3 +- src/actions/transformations/transformation.h | 5 +- src/actions/transformations/trim.cc | 6 -- src/actions/transformations/trim.h | 4 +- src/actions/transformations/trim_left.cc | 9 +-- src/actions/transformations/trim_left.h | 5 +- src/actions/transformations/trim_right.cc | 8 +-- src/actions/transformations/trim_right.h | 5 +- src/actions/transformations/upper_case.cc | 4 -- src/actions/transformations/upper_case.h | 2 +- src/actions/transformations/url_decode.cc | 5 -- src/actions/transformations/url_decode.h | 2 +- src/actions/transformations/url_decode_uni.h | 3 +- src/actions/transformations/url_encode.cc | 6 -- src/actions/transformations/url_encode.h | 2 +- src/actions/transformations/utf8_to_unicode.h | 3 +- src/actions/ver.h | 2 +- src/parser/seclang-parser.cc | 4 +- src/parser/seclang-parser.yy | 4 +- src/rule_with_actions.cc | 8 +-- src/rules_exceptions.cc | 6 +- 96 files changed, 131 insertions(+), 237 deletions(-) diff --git a/headers/modsecurity/actions/action.h b/headers/modsecurity/actions/action.h index b1839fe7..24f0da6d 100644 --- a/headers/modsecurity/actions/action.h +++ b/headers/modsecurity/actions/action.h @@ -32,15 +32,47 @@ namespace actions { class Action { public: + /** + * + * Define the action kind regarding to the execution time. + * + * + */ + enum class Kind { + /** + * + * Action that are executed while loading the configuration. For instance + * the rule ID or the rule phase. + * + */ + ConfigurationKind, + /** + * + * Those are actions that demands to be executed before call the operator. + * For instance the tranformations. + * + * + */ + RunTimeBeforeMatchAttemptKind, + /** + * + * Actions that are executed after the execution of the operator, only if + * the operator returned Match (or True). For instance the disruptive + * actions. + * + */ + RunTimeOnlyIfMatchKind, + }; + explicit Action(const std::string& _action) : m_isNone(false), temporaryAction(false), - action_kind(2), + action_kind(Kind::RunTimeOnlyIfMatchKind), m_name(nullptr), m_parser_payload("") { set_name_and_payload(_action); } - explicit Action(const std::string& _action, int kind) + explicit Action(const std::string& _action, Kind kind) : m_isNone(false), temporaryAction(false), action_kind(kind), @@ -100,41 +132,9 @@ class Action { bool m_isNone; bool temporaryAction; - int action_kind; + Kind action_kind; std::shared_ptr m_name; std::string m_parser_payload; - - /** - * - * Define the action kind regarding to the execution time. - * - * - */ - enum Kind { - /** - * - * Action that are executed while loading the configuration. For instance - * the rule ID or the rule phase. - * - */ - ConfigurationKind, - /** - * - * Those are actions that demands to be executed before call the operator. - * For instance the tranformations. - * - * - */ - RunTimeBeforeMatchAttemptKind, - /** - * - * Actions that are executed after the execution of the operator, only if - * the operator returned Match (or True). For instance the disruptive - * actions. - * - */ - RunTimeOnlyIfMatchKind, - }; }; diff --git a/src/actions/accuracy.h b/src/actions/accuracy.h index f787af19..bbcdba58 100644 --- a/src/actions/accuracy.h +++ b/src/actions/accuracy.h @@ -30,7 +30,7 @@ namespace actions { class Accuracy : public Action { public: explicit Accuracy(const std::string &action) - : Action(action, ConfigurationKind), + : Action(action, Kind::ConfigurationKind), m_accuracy(0) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/audit_log.h b/src/actions/audit_log.h index d870de2a..cde74387 100644 --- a/src/actions/audit_log.h +++ b/src/actions/audit_log.h @@ -33,7 +33,7 @@ namespace actions { class AuditLog : public Action { public: explicit AuditLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/capture.h b/src/actions/capture.h index 33207439..0b072ece 100644 --- a/src/actions/capture.h +++ b/src/actions/capture.h @@ -29,7 +29,7 @@ namespace actions { class Capture : public Action { public: explicit Capture(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/chain.h b/src/actions/chain.h index c5642baa..3b04f17e 100644 --- a/src/actions/chain.h +++ b/src/actions/chain.h @@ -33,7 +33,7 @@ namespace actions { class Chain : public Action { public: explicit Chain(const std::string &action) - : Action(action, ConfigurationKind) { } + : Action(action, Kind::ConfigurationKind) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/audit_engine.h b/src/actions/ctl/audit_engine.h index 03e0cb4c..b822a667 100644 --- a/src/actions/ctl/audit_engine.h +++ b/src/actions/ctl/audit_engine.h @@ -34,7 +34,7 @@ namespace ctl { class AuditEngine : public Action { public: explicit AuditEngine(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_auditEngine(audit_log::AuditLog::AuditLogStatus::NotSetLogStatus) { } bool init(std::string *error) override; diff --git a/src/actions/ctl/audit_log_parts.h b/src/actions/ctl/audit_log_parts.h index f4980780..0eb7c6b2 100644 --- a/src/actions/ctl/audit_log_parts.h +++ b/src/actions/ctl/audit_log_parts.h @@ -29,7 +29,7 @@ namespace ctl { class AuditLogParts : public Action { public: explicit AuditLogParts(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), mPartsAction(0), mParts("") { } diff --git a/src/actions/ctl/request_body_access.h b/src/actions/ctl/request_body_access.h index afe3b3d4..1dcc88c5 100644 --- a/src/actions/ctl/request_body_access.h +++ b/src/actions/ctl/request_body_access.h @@ -30,7 +30,7 @@ namespace ctl { class RequestBodyAccess : public Action { public: explicit RequestBodyAccess(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_request_body_access(false) { } bool init(std::string *error) override; diff --git a/src/actions/ctl/request_body_processor_json.h b/src/actions/ctl/request_body_processor_json.h index 48125597..9d726b17 100644 --- a/src/actions/ctl/request_body_processor_json.h +++ b/src/actions/ctl/request_body_processor_json.h @@ -29,7 +29,7 @@ namespace ctl { class RequestBodyProcessorJSON : public Action { public: explicit RequestBodyProcessorJSON(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/request_body_processor_urlencoded.h b/src/actions/ctl/request_body_processor_urlencoded.h index 5b5557d4..0277664a 100644 --- a/src/actions/ctl/request_body_processor_urlencoded.h +++ b/src/actions/ctl/request_body_processor_urlencoded.h @@ -29,7 +29,7 @@ namespace ctl { class RequestBodyProcessorURLENCODED : public Action { public: explicit RequestBodyProcessorURLENCODED(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/request_body_processor_xml.h b/src/actions/ctl/request_body_processor_xml.h index 9084d1d9..5bd15edd 100644 --- a/src/actions/ctl/request_body_processor_xml.h +++ b/src/actions/ctl/request_body_processor_xml.h @@ -29,7 +29,7 @@ namespace ctl { class RequestBodyProcessorXML : public Action { public: explicit RequestBodyProcessorXML(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/rule_engine.h b/src/actions/ctl/rule_engine.h index fca5d39b..7aef4232 100644 --- a/src/actions/ctl/rule_engine.h +++ b/src/actions/ctl/rule_engine.h @@ -31,7 +31,7 @@ namespace ctl { class RuleEngine : public Action { public: explicit RuleEngine(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_ruleEngine(RulesSetProperties::PropertyNotSetRuleEngine) { } bool init(std::string *error) override; diff --git a/src/actions/ctl/rule_remove_by_id.h b/src/actions/ctl/rule_remove_by_id.h index e0f0902b..f731db31 100644 --- a/src/actions/ctl/rule_remove_by_id.h +++ b/src/actions/ctl/rule_remove_by_id.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveById : public Action { public: explicit RuleRemoveById(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool init(std::string *error) override; bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/ctl/rule_remove_by_tag.h b/src/actions/ctl/rule_remove_by_tag.h index 5689b7b1..e85cdbfa 100644 --- a/src/actions/ctl/rule_remove_by_tag.h +++ b/src/actions/ctl/rule_remove_by_tag.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveByTag : public Action { public: explicit RuleRemoveByTag(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_tag("") { } bool init(std::string *error) override; diff --git a/src/actions/ctl/rule_remove_target_by_id.h b/src/actions/ctl/rule_remove_target_by_id.h index d71e4fc2..92b7286d 100644 --- a/src/actions/ctl/rule_remove_target_by_id.h +++ b/src/actions/ctl/rule_remove_target_by_id.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveTargetById : public Action { public: explicit RuleRemoveTargetById(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_id(0), m_target("") { } diff --git a/src/actions/ctl/rule_remove_target_by_tag.h b/src/actions/ctl/rule_remove_target_by_tag.h index 7863e5a5..b4e21239 100644 --- a/src/actions/ctl/rule_remove_target_by_tag.h +++ b/src/actions/ctl/rule_remove_target_by_tag.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveTargetByTag : public Action { public: explicit RuleRemoveTargetByTag(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool init(std::string *error) override; bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/data/status.h b/src/actions/data/status.h index d792247d..566a927e 100644 --- a/src/actions/data/status.h +++ b/src/actions/data/status.h @@ -33,8 +33,8 @@ namespace data { class Status : public Action { public: - explicit Status(const std::string &action) : Action(action, 2), - m_status(0) { } + explicit Status(const std::string &action) + : Action(action), m_status(0) { } bool init(std::string *error) override; bool evaluate(RuleWithActions *rule, Transaction *transaction, diff --git a/src/actions/disruptive/allow.h b/src/actions/disruptive/allow.h index d9a716ce..a6d538a4 100644 --- a/src/actions/disruptive/allow.h +++ b/src/actions/disruptive/allow.h @@ -54,7 +54,7 @@ enum AllowType : int { class Allow : public Action { public: explicit Allow(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_allowType(NoneAllowType) { } diff --git a/src/actions/disruptive/redirect.h b/src/actions/disruptive/redirect.h index 46b5d51a..72ecf98e 100644 --- a/src/actions/disruptive/redirect.h +++ b/src/actions/disruptive/redirect.h @@ -37,12 +37,12 @@ namespace disruptive { class Redirect : public Action { public: explicit Redirect(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_status(0), m_string(nullptr) { } explicit Redirect(std::unique_ptr z) - : Action("redirert", RunTimeOnlyIfMatchKind), + : Action("redirert"), m_status(0), m_string(std::move(z)) { } diff --git a/src/actions/expire_var.h b/src/actions/expire_var.h index 1b1537bb..f0ca7496 100644 --- a/src/actions/expire_var.h +++ b/src/actions/expire_var.h @@ -36,7 +36,7 @@ class ExpireVar : public Action { explicit ExpireVar(const std::string &action) : Action(action) { } explicit ExpireVar(std::unique_ptr z) - : Action("expirevar", RunTimeOnlyIfMatchKind), + : Action("expirevar"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/init_col.h b/src/actions/init_col.h index 16d7ace9..f5a9263b 100644 --- a/src/actions/init_col.h +++ b/src/actions/init_col.h @@ -35,7 +35,7 @@ class InitCol : public Action { explicit InitCol(const std::string &action) : Action(action) { } InitCol(const std::string &action, std::unique_ptr z) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/log.h b/src/actions/log.h index 736d4a13..d2cb5cd2 100644 --- a/src/actions/log.h +++ b/src/actions/log.h @@ -31,7 +31,7 @@ namespace actions { class Log : public Action { public: explicit Log(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/log_data.h b/src/actions/log_data.h index da2fbf4d..6e618f2a 100644 --- a/src/actions/log_data.h +++ b/src/actions/log_data.h @@ -33,10 +33,10 @@ namespace actions { class LogData : public Action { public: explicit LogData(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } explicit LogData(std::unique_ptr z) - : Action("logdata", RunTimeOnlyIfMatchKind), + : Action("logdata"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, diff --git a/src/actions/maturity.h b/src/actions/maturity.h index dd185efa..3f873af4 100644 --- a/src/actions/maturity.h +++ b/src/actions/maturity.h @@ -30,7 +30,7 @@ namespace actions { class Maturity : public Action { public: explicit Maturity(const std::string &action) - : Action(action, ConfigurationKind), + : Action(action, Kind::ConfigurationKind), m_maturity(0) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/msg.h b/src/actions/msg.h index 61661194..c75e6d6e 100644 --- a/src/actions/msg.h +++ b/src/actions/msg.h @@ -34,10 +34,10 @@ namespace actions { class Msg : public Action { public: explicit Msg(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } explicit Msg(std::unique_ptr z) - : Action("msg", RunTimeOnlyIfMatchKind), + : Action("msg"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, diff --git a/src/actions/multi_match.h b/src/actions/multi_match.h index b0fd2c76..71fe288f 100644 --- a/src/actions/multi_match.h +++ b/src/actions/multi_match.h @@ -33,7 +33,7 @@ namespace actions { class MultiMatch : public Action { public: explicit MultiMatch(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/no_audit_log.h b/src/actions/no_audit_log.h index dbd5d098..6deb5e4a 100644 --- a/src/actions/no_audit_log.h +++ b/src/actions/no_audit_log.h @@ -33,7 +33,7 @@ namespace actions { class NoAuditLog : public Action { public: explicit NoAuditLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/no_log.h b/src/actions/no_log.h index 87d4e305..193a64ea 100644 --- a/src/actions/no_log.h +++ b/src/actions/no_log.h @@ -31,7 +31,7 @@ namespace actions { class NoLog : public Action { public: explicit NoLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/phase.h b/src/actions/phase.h index 0fada3c3..7c814584 100644 --- a/src/actions/phase.h +++ b/src/actions/phase.h @@ -32,7 +32,7 @@ namespace actions { class Phase : public Action { public: - explicit Phase(const std::string &action) : Action(action, ConfigurationKind), + explicit Phase(const std::string &action) : Action(action, Kind::ConfigurationKind), m_phase(0), m_secRulesPhase(0) { } diff --git a/src/actions/rev.h b/src/actions/rev.h index 9e3c1bfb..a023b425 100644 --- a/src/actions/rev.h +++ b/src/actions/rev.h @@ -29,7 +29,7 @@ namespace actions { class Rev : public Action { public: - explicit Rev(const std::string &action) : Action(action, ConfigurationKind) { } + explicit Rev(const std::string &action) : Action(action, Kind::ConfigurationKind) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; diff --git a/src/actions/rule_id.h b/src/actions/rule_id.h index 2e26f87f..8f16c95e 100644 --- a/src/actions/rule_id.h +++ b/src/actions/rule_id.h @@ -33,7 +33,7 @@ namespace actions { class RuleId : public Action { public: explicit RuleId(const std::string &action) - : Action(action, ConfigurationKind), + : Action(action, Kind::ConfigurationKind), m_ruleId(0) { } bool init(std::string *error) override; diff --git a/src/actions/set_env.h b/src/actions/set_env.h index 33ccfc33..cc24c285 100644 --- a/src/actions/set_env.h +++ b/src/actions/set_env.h @@ -36,7 +36,7 @@ class SetENV : public Action { : Action(_action) { } explicit SetENV(std::unique_ptr z) - : Action("setenv", RunTimeOnlyIfMatchKind), + : Action("setenv"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/set_rsc.h b/src/actions/set_rsc.h index 5913b7c7..7830ee92 100644 --- a/src/actions/set_rsc.h +++ b/src/actions/set_rsc.h @@ -36,7 +36,7 @@ class SetRSC : public Action { : Action(_action) { } explicit SetRSC(std::unique_ptr z) - : Action("setsrc", RunTimeOnlyIfMatchKind), + : Action("setsrc"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/set_sid.h b/src/actions/set_sid.h index 64f8f3cc..dca45433 100644 --- a/src/actions/set_sid.h +++ b/src/actions/set_sid.h @@ -36,7 +36,7 @@ class SetSID : public Action { : Action(_action) { } explicit SetSID(std::unique_ptr z) - : Action("setsid", RunTimeOnlyIfMatchKind), + : Action("setsid"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/set_uid.h b/src/actions/set_uid.h index b8c3a0db..76893999 100644 --- a/src/actions/set_uid.h +++ b/src/actions/set_uid.h @@ -36,7 +36,7 @@ class SetUID : public Action { : Action(_action) { } explicit SetUID(std::unique_ptr z) - : Action("setuid", RunTimeOnlyIfMatchKind), + : Action("setuid"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/skip.h b/src/actions/skip.h index 71e5d7aa..ee24abe7 100644 --- a/src/actions/skip.h +++ b/src/actions/skip.h @@ -30,7 +30,7 @@ namespace actions { class Skip : public Action { public: explicit Skip(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_skip_next(0) { } bool init(std::string *error) override; diff --git a/src/actions/skip_after.h b/src/actions/skip_after.h index f7e0680d..39b2c269 100644 --- a/src/actions/skip_after.h +++ b/src/actions/skip_after.h @@ -31,7 +31,7 @@ namespace actions { class SkipAfter : public Action { public: explicit SkipAfter(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_skipName(std::make_shared(m_parser_payload)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/tag.h b/src/actions/tag.h index 75369f5f..bf3988b5 100644 --- a/src/actions/tag.h +++ b/src/actions/tag.h @@ -33,7 +33,7 @@ namespace actions { class Tag : public Action { public: explicit Tag(std::unique_ptr z) - : Action("tag", RunTimeOnlyIfMatchKind), + : Action("tag"), m_string(std::move(z)) { } std::string getName(Transaction *transaction); diff --git a/src/actions/transformations/base64_decode.h b/src/actions/transformations/base64_decode.h index 3527bd5e..8c97dbe8 100644 --- a/src/actions/transformations/base64_decode.h +++ b/src/actions/transformations/base64_decode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class Base64Decode : public Transformation { public: - explicit Base64Decode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/base64_decode_ext.h b/src/actions/transformations/base64_decode_ext.h index 8f1f069e..66b0678f 100644 --- a/src/actions/transformations/base64_decode_ext.h +++ b/src/actions/transformations/base64_decode_ext.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class Base64DecodeExt : public Transformation { public: - explicit Base64DecodeExt(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/base64_encode.h b/src/actions/transformations/base64_encode.h index 7b3ac25e..3c1d96f1 100644 --- a/src/actions/transformations/base64_encode.h +++ b/src/actions/transformations/base64_encode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class Base64Encode : public Transformation { public: - explicit Base64Encode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/cmd_line.h b/src/actions/transformations/cmd_line.h index 9ba5c6b2..27672b60 100644 --- a/src/actions/transformations/cmd_line.h +++ b/src/actions/transformations/cmd_line.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class CmdLine : public Transformation { public: - explicit CmdLine(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/compress_whitespace.cc b/src/actions/transformations/compress_whitespace.cc index 065b4ee0..a9b31c96 100644 --- a/src/actions/transformations/compress_whitespace.cc +++ b/src/actions/transformations/compress_whitespace.cc @@ -19,11 +19,6 @@ namespace modsecurity::actions::transformations { -CompressWhitespace::CompressWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - bool CompressWhitespace::transform(std::string &value, const Transaction *trans) const { bool inWhiteSpace = false; diff --git a/src/actions/transformations/compress_whitespace.h b/src/actions/transformations/compress_whitespace.h index bf90b0ba..8f74a3c1 100644 --- a/src/actions/transformations/compress_whitespace.h +++ b/src/actions/transformations/compress_whitespace.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class CompressWhitespace : public Transformation { public: - explicit CompressWhitespace(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/css_decode.h b/src/actions/transformations/css_decode.h index 67535a9a..c9b451f8 100644 --- a/src/actions/transformations/css_decode.h +++ b/src/actions/transformations/css_decode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class CssDecode : public Transformation { public: - explicit CssDecode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/escape_seq_decode.cc b/src/actions/transformations/escape_seq_decode.cc index 29006144..2cc413e7 100644 --- a/src/actions/transformations/escape_seq_decode.cc +++ b/src/actions/transformations/escape_seq_decode.cc @@ -20,12 +20,6 @@ namespace modsecurity::actions::transformations { -EscapeSeqDecode::EscapeSeqDecode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - - static inline int ansi_c_sequences_decode_inplace(std::string &value) { auto d = reinterpret_cast(value.data()); const unsigned char* input = d; diff --git a/src/actions/transformations/escape_seq_decode.h b/src/actions/transformations/escape_seq_decode.h index 6a240715..71976fe1 100644 --- a/src/actions/transformations/escape_seq_decode.h +++ b/src/actions/transformations/escape_seq_decode.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class EscapeSeqDecode : public Transformation { public: - explicit EscapeSeqDecode(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/hex_decode.h b/src/actions/transformations/hex_decode.h index 158f91aa..1ee6a1b7 100644 --- a/src/actions/transformations/hex_decode.h +++ b/src/actions/transformations/hex_decode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class HexDecode : public Transformation { public: - explicit HexDecode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/hex_encode.cc b/src/actions/transformations/hex_encode.cc index a0719726..689a132f 100644 --- a/src/actions/transformations/hex_encode.cc +++ b/src/actions/transformations/hex_encode.cc @@ -20,10 +20,6 @@ namespace modsecurity::actions::transformations { -HexEncode::HexEncode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} bool HexEncode::transform(std::string &value, const Transaction *trans) const { if (value.empty()) return false; diff --git a/src/actions/transformations/hex_encode.h b/src/actions/transformations/hex_encode.h index 3bb744b5..9037a514 100644 --- a/src/actions/transformations/hex_encode.h +++ b/src/actions/transformations/hex_encode.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class HexEncode : public Transformation { public: - explicit HexEncode(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/html_entity_decode.h b/src/actions/transformations/html_entity_decode.h index 5c17333a..499f8f2f 100644 --- a/src/actions/transformations/html_entity_decode.h +++ b/src/actions/transformations/html_entity_decode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class HtmlEntityDecode : public Transformation { public: - explicit HtmlEntityDecode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/js_decode.h b/src/actions/transformations/js_decode.h index 94156426..840577cb 100644 --- a/src/actions/transformations/js_decode.h +++ b/src/actions/transformations/js_decode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class JsDecode : public Transformation { public: - explicit JsDecode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/length.cc b/src/actions/transformations/length.cc index 10aadfe8..ac98914c 100644 --- a/src/actions/transformations/length.cc +++ b/src/actions/transformations/length.cc @@ -19,11 +19,6 @@ namespace modsecurity::actions::transformations { -Length::Length(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - bool Length::transform(std::string &value, const Transaction *trans) const { value = std::to_string(value.size()); return true; diff --git a/src/actions/transformations/length.h b/src/actions/transformations/length.h index e7b6b081..39465238 100644 --- a/src/actions/transformations/length.h +++ b/src/actions/transformations/length.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class Length : public Transformation { public: - explicit Length(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/lower_case.cc b/src/actions/transformations/lower_case.cc index 080429d9..0238b5a4 100644 --- a/src/actions/transformations/lower_case.cc +++ b/src/actions/transformations/lower_case.cc @@ -22,10 +22,6 @@ namespace modsecurity::actions::transformations { -LowerCase::LowerCase(const std::string &a) - : Transformation(a) { -} - bool LowerCase::transform(std::string &value, const Transaction *trans) const { return convert(value, [](auto c) { return std::tolower(c); }); diff --git a/src/actions/transformations/lower_case.h b/src/actions/transformations/lower_case.h index 7bdf2d84..192b2aa3 100644 --- a/src/actions/transformations/lower_case.h +++ b/src/actions/transformations/lower_case.h @@ -24,7 +24,7 @@ namespace modsecurity::actions::transformations { class LowerCase : public Transformation { public: - explicit LowerCase(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; diff --git a/src/actions/transformations/md5.h b/src/actions/transformations/md5.h index 9d5a15f8..d1813c5f 100644 --- a/src/actions/transformations/md5.h +++ b/src/actions/transformations/md5.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class Md5 : public Transformation { public: - explicit Md5(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/normalise_path.cc b/src/actions/transformations/normalise_path.cc index dd2b64d2..91c04027 100644 --- a/src/actions/transformations/normalise_path.cc +++ b/src/actions/transformations/normalise_path.cc @@ -19,11 +19,6 @@ namespace modsecurity::actions::transformations { -NormalisePath::NormalisePath(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - bool NormalisePath::transform(std::string &value, const Transaction *trans) const { return normalize_path_inplace(value, false); } diff --git a/src/actions/transformations/normalise_path.h b/src/actions/transformations/normalise_path.h index 248def7f..a1ef8918 100644 --- a/src/actions/transformations/normalise_path.h +++ b/src/actions/transformations/normalise_path.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class NormalisePath : public Transformation { public: - explicit NormalisePath(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; diff --git a/src/actions/transformations/normalise_path_win.h b/src/actions/transformations/normalise_path_win.h index af312693..0cf11260 100644 --- a/src/actions/transformations/normalise_path_win.h +++ b/src/actions/transformations/normalise_path_win.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class NormalisePathWin : public Transformation { public: - explicit NormalisePathWin(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/parity_even_7bit.h b/src/actions/transformations/parity_even_7bit.h index 786f72e4..8e107a5d 100644 --- a/src/actions/transformations/parity_even_7bit.h +++ b/src/actions/transformations/parity_even_7bit.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class ParityEven7bit : public Transformation { public: - explicit ParityEven7bit(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; diff --git a/src/actions/transformations/parity_odd_7bit.h b/src/actions/transformations/parity_odd_7bit.h index d0a1583c..0b9164b9 100644 --- a/src/actions/transformations/parity_odd_7bit.h +++ b/src/actions/transformations/parity_odd_7bit.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class ParityOdd7bit : public Transformation { public: - explicit ParityOdd7bit(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/parity_zero_7bit.h b/src/actions/transformations/parity_zero_7bit.h index c7f27d74..aa9d1bf3 100644 --- a/src/actions/transformations/parity_zero_7bit.h +++ b/src/actions/transformations/parity_zero_7bit.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class ParityZero7bit : public Transformation { public: - explicit ParityZero7bit(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/remove_comments.h b/src/actions/transformations/remove_comments.h index 67f0ff5b..948536cb 100644 --- a/src/actions/transformations/remove_comments.h +++ b/src/actions/transformations/remove_comments.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class RemoveComments : public Transformation { public: - explicit RemoveComments(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/remove_comments_char.cc b/src/actions/transformations/remove_comments_char.cc index 2eeb86f6..7e666db3 100644 --- a/src/actions/transformations/remove_comments_char.cc +++ b/src/actions/transformations/remove_comments_char.cc @@ -18,10 +18,6 @@ namespace modsecurity::actions::transformations { -RemoveCommentsChar::RemoveCommentsChar(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} bool RemoveCommentsChar::transform(std::string &value, const Transaction *trans) const { char *d = value.data(); diff --git a/src/actions/transformations/remove_comments_char.h b/src/actions/transformations/remove_comments_char.h index 2066fd65..d11b0148 100644 --- a/src/actions/transformations/remove_comments_char.h +++ b/src/actions/transformations/remove_comments_char.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class RemoveCommentsChar : public Transformation { public: - explicit RemoveCommentsChar(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/remove_nulls.h b/src/actions/transformations/remove_nulls.h index 163f9ddf..67c90ee0 100644 --- a/src/actions/transformations/remove_nulls.h +++ b/src/actions/transformations/remove_nulls.h @@ -24,8 +24,7 @@ namespace modsecurity::actions::transformations { class RemoveNulls : public Transformation { public: - explicit RemoveNulls(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; diff --git a/src/actions/transformations/remove_whitespace.cc b/src/actions/transformations/remove_whitespace.cc index 934f1d29..f7047f47 100644 --- a/src/actions/transformations/remove_whitespace.cc +++ b/src/actions/transformations/remove_whitespace.cc @@ -20,11 +20,6 @@ namespace modsecurity::actions::transformations { -RemoveWhitespace::RemoveWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - bool RemoveWhitespace::transform(std::string &value, const Transaction *trans) const { const char nonBreakingSpaces = 0xa0; const char nonBreakingSpaces2 = 0xc2; diff --git a/src/actions/transformations/remove_whitespace.h b/src/actions/transformations/remove_whitespace.h index a9925f8e..b95a508b 100644 --- a/src/actions/transformations/remove_whitespace.h +++ b/src/actions/transformations/remove_whitespace.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class RemoveWhitespace : public Transformation { public: - explicit RemoveWhitespace(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/replace_comments.cc b/src/actions/transformations/replace_comments.cc index a6bab972..78ae786c 100644 --- a/src/actions/transformations/replace_comments.cc +++ b/src/actions/transformations/replace_comments.cc @@ -59,12 +59,6 @@ static inline bool inplace(std::string &value) { } -ReplaceComments::ReplaceComments(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - - bool ReplaceComments::transform(std::string &value, const Transaction *trans) const { return inplace(value); } diff --git a/src/actions/transformations/replace_comments.h b/src/actions/transformations/replace_comments.h index 95e5e854..db206e53 100644 --- a/src/actions/transformations/replace_comments.h +++ b/src/actions/transformations/replace_comments.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class ReplaceComments : public Transformation { public: - explicit ReplaceComments(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/replace_nulls.cc b/src/actions/transformations/replace_nulls.cc index 479f2f5a..9792da5d 100644 --- a/src/actions/transformations/replace_nulls.cc +++ b/src/actions/transformations/replace_nulls.cc @@ -18,10 +18,6 @@ namespace modsecurity::actions::transformations { -ReplaceNulls::ReplaceNulls(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} bool ReplaceNulls::transform(std::string &value, const Transaction *trans) const { bool changed = false; diff --git a/src/actions/transformations/replace_nulls.h b/src/actions/transformations/replace_nulls.h index ad206ae4..a01077c7 100644 --- a/src/actions/transformations/replace_nulls.h +++ b/src/actions/transformations/replace_nulls.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class ReplaceNulls : public Transformation { public: - explicit ReplaceNulls(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/sha1.cc b/src/actions/transformations/sha1.cc index af1eda41..38863345 100644 --- a/src/actions/transformations/sha1.cc +++ b/src/actions/transformations/sha1.cc @@ -20,14 +20,11 @@ namespace modsecurity::actions::transformations { -Sha1::Sha1(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} bool Sha1::transform(std::string &value, const Transaction *trans) const { value = Utils::Sha1::digest(value); return true; } + } // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/sha1.h b/src/actions/transformations/sha1.h index 263ed978..f7776411 100644 --- a/src/actions/transformations/sha1.h +++ b/src/actions/transformations/sha1.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class Sha1 : public Transformation { public: - explicit Sha1(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/sql_hex_decode.h b/src/actions/transformations/sql_hex_decode.h index 44f45d17..0acb1cff 100644 --- a/src/actions/transformations/sql_hex_decode.h +++ b/src/actions/transformations/sql_hex_decode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class SqlHexDecode : public Transformation { public: - explicit SqlHexDecode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/transformation.h b/src/actions/transformations/transformation.h index 3677dcef..1d0ea99a 100644 --- a/src/actions/transformations/transformation.h +++ b/src/actions/transformations/transformation.h @@ -23,10 +23,7 @@ namespace modsecurity::actions::transformations { class Transformation : public Action { public: explicit Transformation(const std::string& _action) - : Action(_action, RunTimeBeforeMatchAttemptKind) { } - - explicit Transformation(const std::string& _action, int kind) - : Action(_action, kind) { } + : Action(_action, Kind::RunTimeBeforeMatchAttemptKind) { } static Transformation* instantiate(std::string a); diff --git a/src/actions/transformations/trim.cc b/src/actions/transformations/trim.cc index bc90b4ec..2056b256 100644 --- a/src/actions/transformations/trim.cc +++ b/src/actions/transformations/trim.cc @@ -55,12 +55,6 @@ bool Trim::trim(std::string &s) { } -Trim::Trim(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - - bool Trim::transform(std::string &value, const Transaction *trans) const { return trim(value); } diff --git a/src/actions/transformations/trim.h b/src/actions/transformations/trim.h index 0e3d26f6..e436f5bf 100644 --- a/src/actions/transformations/trim.h +++ b/src/actions/transformations/trim.h @@ -22,12 +22,10 @@ namespace modsecurity::actions::transformations { class Trim : public Transformation { public: - explicit Trim(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; - protected: - static bool ltrim(std::string &s); static bool rtrim(std::string &s); static bool trim(std::string &s); diff --git a/src/actions/transformations/trim_left.cc b/src/actions/transformations/trim_left.cc index 10276acf..2ce70149 100644 --- a/src/actions/transformations/trim_left.cc +++ b/src/actions/transformations/trim_left.cc @@ -14,19 +14,14 @@ */ #include "trim_left.h" +#include "trim.h" namespace modsecurity::actions::transformations { - -TrimLeft::TrimLeft(const std::string &action) - : Trim(action) { - this->action_kind = 1; -} - bool TrimLeft::transform(std::string &value, const Transaction *trans) const { - return ltrim(value); + return Trim::ltrim(value); } diff --git a/src/actions/transformations/trim_left.h b/src/actions/transformations/trim_left.h index 5d5a0a57..8acf1fe5 100644 --- a/src/actions/transformations/trim_left.h +++ b/src/actions/transformations/trim_left.h @@ -17,13 +17,12 @@ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ #include "transformation.h" -#include "trim.h" namespace modsecurity::actions::transformations { -class TrimLeft : public Trim { +class TrimLeft : public Transformation { public: - explicit TrimLeft(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/trim_right.cc b/src/actions/transformations/trim_right.cc index aa38c348..e6536786 100644 --- a/src/actions/transformations/trim_right.cc +++ b/src/actions/transformations/trim_right.cc @@ -14,18 +14,14 @@ */ #include "trim_right.h" +#include "trim.h" namespace modsecurity::actions::transformations { -TrimRight::TrimRight(const std::string &action) - : Trim(action) { - this->action_kind = 1; -} - bool TrimRight::transform(std::string &value, const Transaction *trans) const { - return rtrim(value); + return Trim::rtrim(value); } diff --git a/src/actions/transformations/trim_right.h b/src/actions/transformations/trim_right.h index eb13fb20..7e31795a 100644 --- a/src/actions/transformations/trim_right.h +++ b/src/actions/transformations/trim_right.h @@ -17,13 +17,12 @@ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ #include "transformation.h" -#include "trim.h" namespace modsecurity::actions::transformations { -class TrimRight : public Trim { +class TrimRight : public Transformation { public: - explicit TrimRight(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/upper_case.cc b/src/actions/transformations/upper_case.cc index f811bcbb..2b3978c7 100644 --- a/src/actions/transformations/upper_case.cc +++ b/src/actions/transformations/upper_case.cc @@ -24,10 +24,6 @@ namespace modsecurity::actions::transformations { -UpperCase::UpperCase(const std::string &a) - : Transformation(a) { -} - bool UpperCase::transform(std::string &value, const Transaction *trans) const { return LowerCase::convert(value, [](auto c) { return std::toupper(c); }); diff --git a/src/actions/transformations/upper_case.h b/src/actions/transformations/upper_case.h index 70c806b0..87a1df8a 100644 --- a/src/actions/transformations/upper_case.h +++ b/src/actions/transformations/upper_case.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class UpperCase : public Transformation { public: - explicit UpperCase(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index c67e9fa6..dbc7bf9f 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -21,11 +21,6 @@ namespace modsecurity::actions::transformations { -UrlDecode::UrlDecode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - bool UrlDecode::transform(std::string &value, const Transaction *trans) const { int invalid_count; return utils::urldecode_nonstrict_inplace(value, invalid_count); diff --git a/src/actions/transformations/url_decode.h b/src/actions/transformations/url_decode.h index 5c5c2662..cc73c9c3 100644 --- a/src/actions/transformations/url_decode.h +++ b/src/actions/transformations/url_decode.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class UrlDecode : public Transformation { public: - explicit UrlDecode(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/url_decode_uni.h b/src/actions/transformations/url_decode_uni.h index 8dbac462..046f251a 100644 --- a/src/actions/transformations/url_decode_uni.h +++ b/src/actions/transformations/url_decode_uni.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class UrlDecodeUni : public Transformation { public: - explicit UrlDecodeUni(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/url_encode.cc b/src/actions/transformations/url_encode.cc index 36fef771..2692a2d3 100644 --- a/src/actions/transformations/url_encode.cc +++ b/src/actions/transformations/url_encode.cc @@ -20,12 +20,6 @@ namespace modsecurity::actions::transformations { -UrlEncode::UrlEncode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - - static inline bool url_enc(std::string &value) { const auto len = value.size() * 3 + 1; std::string ret(len, {}); diff --git a/src/actions/transformations/url_encode.h b/src/actions/transformations/url_encode.h index 4f3ffe73..e112fb57 100644 --- a/src/actions/transformations/url_encode.h +++ b/src/actions/transformations/url_encode.h @@ -22,7 +22,7 @@ namespace modsecurity::actions::transformations { class UrlEncode : public Transformation { public: - explicit UrlEncode(const std::string &action); + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/transformations/utf8_to_unicode.h b/src/actions/transformations/utf8_to_unicode.h index bbb6cdc4..af125338 100644 --- a/src/actions/transformations/utf8_to_unicode.h +++ b/src/actions/transformations/utf8_to_unicode.h @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { class Utf8ToUnicode : public Transformation { public: - explicit Utf8ToUnicode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; bool transform(std::string &value, const Transaction *trans) const override; }; diff --git a/src/actions/ver.h b/src/actions/ver.h index 364d567b..8bce189c 100644 --- a/src/actions/ver.h +++ b/src/actions/ver.h @@ -29,7 +29,7 @@ namespace actions { class Ver : public Action { public: - explicit Ver(const std::string &action) : Action(action, ConfigurationKind) { } + explicit Ver(const std::string &action) : Action(action, Kind::ConfigurationKind) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/parser/seclang-parser.cc b/src/parser/seclang-parser.cc index 767b8b22..fbce5704 100644 --- a/src/parser/seclang-parser.cc +++ b/src/parser/seclang-parser.cc @@ -2424,8 +2424,8 @@ namespace yy { definedPhase = phase->m_phase; secRuleDefinedPhase = phase->m_secRulesPhase; delete phase; - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind || - a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) { + } else if (a->action_kind == actions::Action::Kind::RunTimeOnlyIfMatchKind || + a->action_kind == actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { actions::transformations::None *none = dynamic_cast(a); if (none != NULL) { driver.error(yystack_[2].location, "The transformation none is not suitable to be part of the SecDefaultActions"); diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index f6610951..41583768 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -1199,8 +1199,8 @@ expression: definedPhase = phase->m_phase; secRuleDefinedPhase = phase->m_secRulesPhase; delete phase; - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind || - a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) { + } else if (a->action_kind == actions::Action::Kind::RunTimeOnlyIfMatchKind || + a->action_kind == actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { actions::transformations::None *none = dynamic_cast(a); if (none != NULL) { driver.error(@0, "The transformation none is not suitable to be part of the SecDefaultActions"); diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index 7aa0e649..1cde8005 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -89,11 +89,11 @@ RuleWithActions::RuleWithActions( if (actions) { for (Action *a : *actions) { switch (a->action_kind) { - case Action::ConfigurationKind: + case Action::Kind::ConfigurationKind: a->evaluate(this, NULL); delete a; break; - case Action::RunTimeOnlyIfMatchKind: + case Action::Kind::RunTimeOnlyIfMatchKind: if (dynamic_cast(a)) { m_containsCaptureAction = true; delete a; @@ -247,7 +247,7 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, bool disruptiveAlreadyExecuted = false; for (const auto &a : trans->m_rules->m_defaultActions[getPhase()]) { // cppcheck-suppress ctunullpointer - if (a.get()->action_kind != actions::Action::RunTimeOnlyIfMatchKind) { + if (a.get()->action_kind != actions::Action::Kind::RunTimeOnlyIfMatchKind) { continue; } if (!a.get()->isDisruptive()) { @@ -374,7 +374,7 @@ void RuleWithActions::executeTransformations( if (none == 0) { for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) { if (a->action_kind \ - != actions::Action::RunTimeBeforeMatchAttemptKind) { + != actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { continue; } diff --git a/src/rules_exceptions.cc b/src/rules_exceptions.cc index 1349866d..71cf28c2 100644 --- a/src/rules_exceptions.cc +++ b/src/rules_exceptions.cc @@ -36,15 +36,15 @@ bool RulesExceptions::loadUpdateActionById(double id, std::string *error) { for (auto &a : *actions) { - if (a->action_kind == actions::Action::ConfigurationKind) { + if (a->action_kind == actions::Action::Kind::ConfigurationKind) { std::cout << "General failure, action: " << a->m_name; std::cout << " has not expected to be used with UpdateActionByID."; std::cout << std::endl; } else if (a->action_kind - == actions::Action::RunTimeBeforeMatchAttemptKind) { + == actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { m_action_pre_update_target_by_id.emplace(std::pair>(id , std::move(a))); - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) { + } else if (a->action_kind == actions::Action::Kind::RunTimeOnlyIfMatchKind) { m_action_pos_update_target_by_id.emplace(std::pair>(id , std::move(a))); } else { From a6d64bf615f9bce451bc5132f60a9bcfabb26901 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Sat, 17 Aug 2024 00:53:54 +0000 Subject: [PATCH 72/75] Replaced VALID_HEX, ISODIGIT & NBSP macros in string.h - Moved them into modsecurity::utils::string to avoid polluting the global namespace. --- src/actions/transformations/css_decode.cc | 1 + .../transformations/escape_seq_decode.cc | 2 ++ .../transformations/html_entity_decode.cc | 1 + src/actions/transformations/js_decode.cc | 1 + src/actions/transformations/sql_hex_decode.cc | 1 + src/actions/transformations/url_decode_uni.cc | 1 + src/utils/decode.cc | 7 ++--- src/utils/string.h | 28 +++++++++++-------- 8 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/actions/transformations/css_decode.cc b/src/actions/transformations/css_decode.cc index c5de63f7..41da9390 100644 --- a/src/actions/transformations/css_decode.cc +++ b/src/actions/transformations/css_decode.cc @@ -17,6 +17,7 @@ #include "src/utils/string.h" +using namespace modsecurity::utils::string; namespace modsecurity::actions::transformations { diff --git a/src/actions/transformations/escape_seq_decode.cc b/src/actions/transformations/escape_seq_decode.cc index 2cc413e7..94df2269 100644 --- a/src/actions/transformations/escape_seq_decode.cc +++ b/src/actions/transformations/escape_seq_decode.cc @@ -17,6 +17,8 @@ #include "src/utils/string.h" +using namespace modsecurity::utils::string; + namespace modsecurity::actions::transformations { diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index 0b9d811b..8a0cc3e9 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -23,6 +23,7 @@ #include "src/compat/msvc.h" #endif +using namespace modsecurity::utils::string; namespace modsecurity::actions::transformations { diff --git a/src/actions/transformations/js_decode.cc b/src/actions/transformations/js_decode.cc index 394a2cdc..857125c7 100644 --- a/src/actions/transformations/js_decode.cc +++ b/src/actions/transformations/js_decode.cc @@ -17,6 +17,7 @@ #include "src/utils/string.h" +using namespace modsecurity::utils::string; namespace modsecurity::actions::transformations { diff --git a/src/actions/transformations/sql_hex_decode.cc b/src/actions/transformations/sql_hex_decode.cc index 8f19e619..0ce24087 100644 --- a/src/actions/transformations/sql_hex_decode.cc +++ b/src/actions/transformations/sql_hex_decode.cc @@ -19,6 +19,7 @@ #include "src/utils/string.h" +using namespace modsecurity::utils::string; namespace modsecurity::actions::transformations { diff --git a/src/actions/transformations/url_decode_uni.cc b/src/actions/transformations/url_decode_uni.cc index 57df7a56..58d683c8 100644 --- a/src/actions/transformations/url_decode_uni.cc +++ b/src/actions/transformations/url_decode_uni.cc @@ -18,6 +18,7 @@ #include "modsecurity/rules_set.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; namespace modsecurity::actions::transformations { diff --git a/src/utils/decode.cc b/src/utils/decode.cc index 32d95301..2735cf3e 100644 --- a/src/utils/decode.cc +++ b/src/utils/decode.cc @@ -17,9 +17,9 @@ #include "modsecurity/modsecurity.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; -namespace modsecurity { -namespace utils { +namespace modsecurity::utils { bool urldecode_nonstrict_inplace(std::string &val, @@ -112,5 +112,4 @@ std::string uri_decode(const std::string & sSrc) { } -} // namespace utils -} // namespace modsecurity +} // namespace modsecurity::utils diff --git a/src/utils/string.h b/src/utils/string.h index dbfb9b47..f5e52ff0 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -13,6 +13,9 @@ * */ +#ifndef SRC_UTILS_STRING_H_ +#define SRC_UTILS_STRING_H_ + #include #include #include @@ -27,18 +30,21 @@ #include "src/compat/msvc.h" #endif -#ifndef SRC_UTILS_STRING_H_ -#define SRC_UTILS_STRING_H_ +namespace modsecurity::utils::string { -#define VALID_HEX(X) (((X >= '0') && (X <= '9')) || \ - ((X >= 'a') && (X <= 'f')) || ((X >= 'A') && (X <= 'F'))) -#define ISODIGIT(X) ((X >= '0') && (X <= '7')) -#define NBSP 160 +template +constexpr bool VALID_HEX(CharT X) { + return ((X >= '0') && (X <= '9')) + || ((X >= 'a') && (X <= 'f')) + || ((X >= 'A') && (X <= 'F')); +} +template +constexpr bool ISODIGIT(CharT X) { + return (X >= '0') && (X <= '7'); +} -namespace modsecurity { -namespace utils { -namespace string { +constexpr unsigned char NBSP = 160; const char HEX2DEC[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ @@ -271,8 +277,6 @@ inline std::string toupper(std::string str) { // cppcheck-suppress passedByValue } -} // namespace string -} // namespace utils -} // namespace modsecurity +} // namespace modsecurity::utils::string #endif // SRC_UTILS_STRING_H_ From 3e9d8107a86bea0c4329798a4a8d385db36aaa72 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Fri, 9 Aug 2024 13:01:37 -0700 Subject: [PATCH 73/75] Removed multiple heap-allocated copies in parse_pm_content - The previous version of this function was doing three strdup copies to parse the pm content. The updated version only copies the value once (in order not to modify the Operator's m_param member variable), and then performs the updates inline. - Binary parsing was broken because digits were not compared as characters. - Fail parsing when an invalid hex character is found. - Error message in parse_pm_content would reference freed memory if accessed by caller. Removed anyway because it was unused. --- src/Makefile.am | 1 - src/operators/pm.cc | 103 +++++++++++++++++++++++---------- src/operators/pm.h | 1 - src/operators/pm_f.cc | 27 --------- src/utils/acmp.cc | 129 +----------------------------------------- src/utils/acmp.h | 3 +- 6 files changed, 75 insertions(+), 189 deletions(-) delete mode 100644 src/operators/pm_f.cc diff --git a/src/Makefile.am b/src/Makefile.am index 6f358655..75f2ee4a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -219,7 +219,6 @@ OPERATORS = \ operators/no_match.cc \ operators/operator.cc \ operators/pm.cc \ - operators/pm_f.cc \ operators/pm_from_file.cc \ operators/rbl.cc \ operators/rsub.cc \ diff --git a/src/operators/pm.cc b/src/operators/pm.cc index ba7039bf..754746e8 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -15,20 +15,80 @@ #include "src/operators/pm.h" -#include - -#include #include #include #include -#include -#include -#include -#include "src/operators/operator.h" #include "src/utils/acmp.h" #include "src/utils/string.h" + +static inline std::string parse_pm_content(const std::string &op_parm) { + auto offset = op_parm.find_first_not_of(" \t"); + if (offset == std::string::npos) { + return op_parm; + } + + auto size = op_parm.size() - offset; + if (size >= 2 && + op_parm.at(offset) == '\"' && op_parm.back() == '\"') { + offset++; + size -= 2; + } + + if (size == 0) { + return op_parm; + } + + std::string parsed_parm(op_parm.c_str() + offset, size); + + unsigned char bin_offset = 0; + unsigned char bin_parm[3] = { 0 }; + bool bin = false, esc = false; + + char *d = parsed_parm.data(); + for(const char *s = d, *e = d + size; s != e; ++s) { + if (*s == '|') { + bin = !bin; + } else if(!esc && *s == '\\') { + esc = true; + } else { + if (bin) { + if (VALID_HEX(*s)) { + bin_parm[bin_offset] = (char)*s; + bin_offset++; + if (bin_offset == 2) { + unsigned char c = strtol((char *)bin_parm, (char **) nullptr, 16) & 0xFF; + bin_offset = 0; + *d++ = c; + } + } else { + // Invalid hex character + return op_parm; + } + } else if (esc) { + if (*s == ':' || + *s == ';' || + *s == '\\' || + *s == '\"') + { + *d++ = *s; + } else { + // Unsupported escape sequence + return op_parm; + } + esc = false; + } else { + *d++ = *s; + } + } + } + + parsed_parm.resize(d - parsed_parm.c_str()); + return parsed_parm; +} + + namespace modsecurity { namespace operators { @@ -105,36 +165,19 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, bool Pm::init(const std::string &file, std::string *error) { - std::vector vec; - std::istringstream *iss; - const char *err = NULL; + const auto op_parm = parse_pm_content(m_param); - char *content = parse_pm_content(m_param.c_str(), m_param.length(), &err); - if (content == NULL) { - iss = new std::istringstream(m_param); - } else { - iss = new std::istringstream(content); - } - - std::copy(std::istream_iterator(*iss), + std::istringstream iss{op_parm}; + std::for_each(std::istream_iterator(iss), std::istream_iterator(), - back_inserter(vec)); - - for (auto &a : vec) { - acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length()); - } + [this](const auto &a) { + acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length()); + }); while (m_p->is_failtree_done == 0) { acmp_prepare(m_p); } - if (content) { - free(content); - content = NULL; - } - - delete iss; - return true; } diff --git a/src/operators/pm.h b/src/operators/pm.h index d07ba46c..72d3a546 100644 --- a/src/operators/pm.h +++ b/src/operators/pm.h @@ -17,7 +17,6 @@ #define SRC_OPERATORS_PM_H_ #include -#include #include #include #include diff --git a/src/operators/pm_f.cc b/src/operators/pm_f.cc deleted file mode 100644 index bc83a33b..00000000 --- a/src/operators/pm_f.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/) - * - * You may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * If any of the files related to licensing are missing or if you have any - * other questions related to licensing please contact Trustwave Holdings, Inc. - * directly using the email address security@modsecurity.org. - * - */ - -#include "src/operators/pm_f.h" - -#include - -#include "src/operators/pm_from_file.h" - -namespace modsecurity { -namespace operators { - - -} // namespace operators -} // namespace modsecurity diff --git a/src/utils/acmp.cc b/src/utils/acmp.cc index 708ce3a2..fb61f31d 100644 --- a/src/utils/acmp.cc +++ b/src/utils/acmp.cc @@ -33,136 +33,9 @@ * that should be mitigated. This ACMP parser should be re-written to * consume less memory. */ + extern "C" { -char *parse_pm_content(const char *op_parm, unsigned short int op_len, const char **error_msg) { - char *parm = NULL; - char *content; - unsigned short int offset = 0; -// char converted = 0; - int i, x; - unsigned char bin = 0, esc = 0, bin_offset = 0; - unsigned char c = 0; - unsigned char bin_parm[3] = { 0 }; - char *processed = NULL; - - content = strdup(op_parm); - - if (content == NULL) { - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - return NULL; - } - - while (offset < op_len && (content[offset] == ' ' || content[offset] == '\t')) { - offset++; - }; - - op_len = strlen(content); - - if (content[offset] == '\"' && content[op_len-1] == '\"') { - parm = strdup(content + offset + 1); - if (parm == NULL) { - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - free(content); - content = NULL; - return NULL; - } - parm[op_len - offset - 2] = '\0'; - } else { - parm = strdup(content + offset); - if (parm == NULL) { - free(content); - content = NULL; - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - return NULL; - } - } - - free(content); - content = NULL; - - op_len = strlen(parm); - - if (op_len == 0) { - *error_msg = "Content length is 0."; - free(parm); - return NULL; - } - - for (i = 0, x = 0; i < op_len; i++) { - if (parm[i] == '|') { - if (bin) { - bin = 0; - } else { - bin = 1; - } - } else if(!esc && parm[i] == '\\') { - esc = 1; - } else { - if (bin) { - if (parm[i] == 0 || parm[i] == 1 || parm[i] == 2 || - parm[i] == 3 || parm[i] == 4 || parm[i] == 5 || - parm[i] == 6 || parm[i] == 7 || parm[i] == 8 || - parm[i] == 9 || - parm[i] == 'A' || parm[i] == 'a' || - parm[i] == 'B' || parm[i] == 'b' || - parm[i] == 'C' || parm[i] == 'c' || - parm[i] == 'D' || parm[i] == 'd' || - parm[i] == 'E' || parm[i] == 'e' || - parm[i] == 'F' || parm[i] == 'f') - { - bin_parm[bin_offset] = (char)parm[i]; - bin_offset++; - if (bin_offset == 2) { - c = strtol((char *)bin_parm, (char **) NULL, 16) & 0xFF; - bin_offset = 0; - parm[x] = c; - x++; - //converted = 1; - } - } else if (parm[i] == ' ') { - } - } else if (esc) { - if (parm[i] == ':' || - parm[i] == ';' || - parm[i] == '\\' || - parm[i] == '\"') - { - parm[x] = parm[i]; - x++; - } else { - *error_msg = std::string("Unsupported escape sequence.").c_str(); - free(parm); - return NULL; - } - esc = 0; - //converted = 1; - } else { - parm[x] = parm[i]; - x++; - } - } - } - -#if 0 - if (converted) { - op_len = x; - } -#endif - - //processed = memcpy(processed, parm, op_len); - processed = strdup(parm); - free(parm); - parm = NULL; - - if (processed == NULL) { - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - return NULL; - } - - return processed; -} - /* ******************************************************************************* ******************************************************************************* diff --git a/src/utils/acmp.h b/src/utils/acmp.h index 1af454e1..a93165fe 100644 --- a/src/utils/acmp.h +++ b/src/utils/acmp.h @@ -23,6 +23,7 @@ #endif #include +#include extern "C" { @@ -189,8 +190,6 @@ int acmp_process_quick(ACMPT *acmpt, const char **match, const char *data, size_ */ int acmp_prepare(ACMP *parser); -char *parse_pm_content(const char *op_parm, unsigned short int op_len, const char **error_msg); - } #endif /*ACMP_H_*/ From 27cc8edbfe6b9996d927f31cc3662b265c3bd2b4 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Wed, 28 Aug 2024 10:13:12 -0300 Subject: [PATCH 74/75] Adjust reference to modsecurity::utils::string::VALID_HEX - This function (previously a #define) was previously in the global namespace and was moved into modsecurity::utils::string in commit a6d64bf. --- src/operators/pm.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/operators/pm.cc b/src/operators/pm.cc index 754746e8..ccd809e1 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -22,6 +22,7 @@ #include "src/utils/acmp.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; static inline std::string parse_pm_content(const std::string &op_parm) { auto offset = op_parm.find_first_not_of(" \t"); From a4604b66f773ba27b0007916a06e2c3d02c87986 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 28 Aug 2024 15:17:38 +0200 Subject: [PATCH 75/75] Added new tests to op @pm --- test/test-cases/regression/operator-pm.json | 80 ++++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/test/test-cases/regression/operator-pm.json b/test/test-cases/regression/operator-pm.json index 4f94d6ea..2261ebe9 100644 --- a/test/test-cases/regression/operator-pm.json +++ b/test/test-cases/regression/operator-pm.json @@ -3,7 +3,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "pm operator test 1/4", + "title": "pm operator test 1/6", "client": { "ip": "200.249.12.31", "port": 2313 @@ -77,7 +77,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "pm operater test 3/4", + "title": "pm operater test 3/6", "client": { "ip": "200.249.12.31", "port": 2313 @@ -114,7 +114,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "pm operater test 4/4", + "title": "pm operater test 4/6", "client": { "ip": "200.249.12.31", "port": 2313 @@ -146,5 +146,79 @@ "SecRuleEngine On", "SecRule ARGS \"@pm a ` b\" \"phase:1,id:999,deny,status:500\"" ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "pm operater test 5/6", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "net.tutsplus.com" + }, + "uri": "\/test.pl?param1=123", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "text\/xml; charset=utf-8\n\r", + "Content-Length": "length\n\r" + } + }, + "expected": { + "debug_log": "Rule returned 1", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecRule ARGS \"@pm 1 2 3\" \"phase:1,id:999,deny\"" + ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "pm operater test 6/6", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "net.tutsplus.com" + }, + "uri": "\/test.pl?param1=abc", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "text\/xml; charset=utf-8\n\r", + "Content-Length": "length\n\r" + } + }, + "expected": { + "debug_log": "Rule returned 0", + "http_code": 200 + }, + "rules": [ + "SecRuleEngine On", + "SecRule ARGS \"@pm 1 2 3\" \"phase:1,id:999,deny\"" + ] } ]