From 2ee5d4ca8fdcb3c8874e66111db3c26ff4367a89 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Wed, 4 Nov 2015 00:28:04 -0300 Subject: [PATCH] Testing performance enhancements by enabling transformations cache Also reduce the utilization of dynamic cast. --- src/actions/action.h | 3 +++ .../transformations/html_entity_decode.cc | 7 +++++++ .../transformations/html_entity_decode.h | 13 +++++++++++++ src/actions/transformations/lower_case.cc | 8 ++++++++ src/actions/transformations/lower_case.h | 12 ++++++++++++ src/actions/transformations/none.h | 3 ++- src/actions/transformations/url_decode.cc | 6 ++++++ src/actions/transformations/url_decode.h | 13 +++++++++++++ src/rule.cc | 19 ++++++------------- src/variables/variable.cc | 8 ++++++-- src/variables/variable.h | 2 ++ src/variables/variations/exclusion.h | 3 ++- 12 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/actions/action.h b/src/actions/action.h index a6cb387b..c01e624c 100644 --- a/src/actions/action.h +++ b/src/actions/action.h @@ -36,6 +36,7 @@ class Action { : action_kind(2), action(_action), name(_action), + m_isNone(false), temporaryAction(false) { name.erase(0, 2); } @@ -43,6 +44,7 @@ class Action { : action_kind(kind), action(_action), name(_action), + m_isNone(false), temporaryAction(false) { name.erase(0, 2); } @@ -94,6 +96,7 @@ class Action { virtual void fill_intervention(ModSecurityIntervention *intervention); bool temporaryAction; + bool m_isNone; }; diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index 0274d80f..e22c5419 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -36,12 +36,19 @@ namespace transformations { std::string HtmlEntityDecode::evaluate(std::string value, Assay *assay) { + + if (HtmlEntityDecodeInstantCache::getInstance().count(value) > 0) { + return HtmlEntityDecodeInstantCache::getInstance().at(value); + } + char *tmp = strdup(value.c_str()); html_entities_decode_inplace((unsigned char *)tmp, value.size()); std::string ret(""); ret.assign(tmp); free(tmp); + HtmlEntityDecodeInstantCache::getInstance().emplace(value, ret); + return ret; } diff --git a/src/actions/transformations/html_entity_decode.h b/src/actions/transformations/html_entity_decode.h index 59158516..131ebef5 100644 --- a/src/actions/transformations/html_entity_decode.h +++ b/src/actions/transformations/html_entity_decode.h @@ -14,6 +14,7 @@ */ #include +#include #include "actions/action.h" #include "actions/transformations/transformation.h" @@ -29,6 +30,18 @@ namespace actions { namespace transformations { +class HtmlEntityDecodeInstantCache : public std::unordered_map { + public: + static HtmlEntityDecodeInstantCache& getInstance() { + static HtmlEntityDecodeInstantCache instance; + return instance; + } + + private: + HtmlEntityDecodeInstantCache() {}; +}; + + class HtmlEntityDecode : public Transformation { public: explicit HtmlEntityDecode(std::string action) diff --git a/src/actions/transformations/lower_case.cc b/src/actions/transformations/lower_case.cc index 06b581f9..a2c98edb 100644 --- a/src/actions/transformations/lower_case.cc +++ b/src/actions/transformations/lower_case.cc @@ -35,10 +35,18 @@ std::string LowerCase::evaluate(std::string value, Assay *assay) { std::locale loc; + if (LowerCaseInstantCache::getInstance().count(value) > 0) { + return LowerCaseInstantCache::getInstance().at(value); + } + + std::string orig_value = value; + for (std::string::size_type i=0; i < value.length(); ++i) { value[i] = std::tolower(value[i], loc); } + LowerCaseInstantCache::getInstance().emplace(orig_value, value); + return value; } diff --git a/src/actions/transformations/lower_case.h b/src/actions/transformations/lower_case.h index 869d9f02..80e8addf 100644 --- a/src/actions/transformations/lower_case.h +++ b/src/actions/transformations/lower_case.h @@ -14,6 +14,7 @@ */ #include +#include #include "actions/action.h" #include "actions/transformations/transformation.h" @@ -28,6 +29,17 @@ class Assay; namespace actions { namespace transformations { +class LowerCaseInstantCache : public std::unordered_map { + public: + static LowerCaseInstantCache& getInstance() { + static LowerCaseInstantCache instance; + return instance; + } + + private: + LowerCaseInstantCache() {}; +}; + class LowerCase : public Transformation { public: diff --git a/src/actions/transformations/none.h b/src/actions/transformations/none.h index f8e6dc46..75deb678 100644 --- a/src/actions/transformations/none.h +++ b/src/actions/transformations/none.h @@ -31,7 +31,8 @@ namespace transformations { class None : public Transformation { public: explicit None(std::string action) - : Transformation(action) { } + : Transformation(action) + { m_isNone = true; } std::string evaluate(std::string exp, Assay *assay) override; diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index 31fe94b7..176f734b 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -100,6 +100,10 @@ std::string UrlDecode::evaluate(std::string value, int invalid_count; int changed; + if (UrlDecodeInstantCache::getInstance().count(value) > 0) { + return UrlDecodeInstantCache::getInstance().at(value); + } + val = (unsigned char *) malloc(sizeof(char) * value.size() + 1); memcpy(val, value.c_str(), value.size() + 1); val[value.size()] = '\0'; @@ -112,6 +116,8 @@ std::string UrlDecode::evaluate(std::string value, free(val); + UrlDecodeInstantCache::getInstance().emplace(value, out); + return out; } diff --git a/src/actions/transformations/url_decode.h b/src/actions/transformations/url_decode.h index dad317d6..a2f2c587 100644 --- a/src/actions/transformations/url_decode.h +++ b/src/actions/transformations/url_decode.h @@ -14,6 +14,7 @@ */ #include +#include #include "actions/action.h" #include "actions/transformations/transformation.h" @@ -28,6 +29,18 @@ class Assay; namespace actions { namespace transformations { +class UrlDecodeInstantCache : public std::unordered_map { + public: + static UrlDecodeInstantCache& getInstance() { + static UrlDecodeInstantCache instance; + return instance; + } + + private: + UrlDecodeInstantCache() {}; +}; + + class UrlDecode : public Transformation { public: explicit UrlDecode(std::string action); diff --git a/src/rule.cc b/src/rule.cc index 0c3b61bf..e4c6fc55 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -140,8 +140,7 @@ bool Rule::evaluateActions(Assay *assay) { bool containsDisruptive = false; // int transformations = 0; for (Action *a : this->actions_runtime_pre) { - None *z = dynamic_cast(a); - if (z != NULL) { + if (a->m_isNone) { none++; } } @@ -165,7 +164,6 @@ bool Rule::evaluateActions(Assay *assay) { } for (Action *a : this->actions_runtime_pre) { - None *z = dynamic_cast(a); /* if (none == 0) { value = a->evaluate(value, assay); @@ -175,7 +173,7 @@ bool Rule::evaluateActions(Assay *assay) { transformations++; } */ - if (z != NULL) { + if (a->m_isNone) { none--; } } @@ -281,9 +279,7 @@ bool Rule::evaluate(Assay *assay) { std::list exclusions; for (int i = 0; i < variables->size(); i++) { Variable *variable = variables->at(i); - Exclusion *exl = dynamic_cast(variable); - - if (exl != NULL) { + if (variable->m_isExclusion) { std::list *z = variable->evaluate(assay); for (auto &y : *z) { @@ -297,8 +293,7 @@ bool Rule::evaluate(Assay *assay) { for (int i = 0; i < variables->size(); i++) { int transformations = 0; Variable *variable = variables->at(i); - Exclusion *exl = dynamic_cast(variable); - if (exl != NULL) { + if (variable->m_isExclusion) { continue; } @@ -317,8 +312,7 @@ bool Rule::evaluate(Assay *assay) { std::string value = v->m_value; int none = 0; for (Action *a : this->actions_runtime_pre) { - None *z = dynamic_cast(a); - if (z != NULL) { + if (a->m_isNone != NULL) { none++; } } @@ -342,7 +336,6 @@ bool Rule::evaluate(Assay *assay) { } for (Action *a : this->actions_runtime_pre) { - None *z = dynamic_cast(a); if (none == 0) { value = a->evaluate(value, assay); #ifndef NO_LOGS @@ -352,7 +345,7 @@ bool Rule::evaluate(Assay *assay) { #endif transformations++; } - if (z != NULL) { + if (a->m_isNone != NULL) { none--; } } diff --git a/src/variables/variable.cc b/src/variables/variable.cc index df4ef3de..a9ab0ec0 100644 --- a/src/variables/variable.cc +++ b/src/variables/variable.cc @@ -31,7 +31,9 @@ namespace Variables { Variable::Variable(std::string name) : m_name(name), - m_collectionName("") { + m_collectionName(""), + m_isExclusion(false), + m_isCount(false) { if (m_name.at(0) == '\\') { m_type = RegularExpression; @@ -53,7 +55,9 @@ Variable::Variable(std::string name) Variable::Variable(std::string name, VariableKind kind) : m_name(name), m_collectionName(""), - m_kind(kind) { + m_kind(kind), + m_isExclusion(false), + m_isCount(false) { if (m_name.at(0) == '\\') { m_type = RegularExpression; diff --git a/src/variables/variable.h b/src/variables/variable.h index ada55480..8e999fec 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -74,6 +74,8 @@ class Variable { VariableType m_type; VariableKind m_kind; + bool m_isExclusion; + bool m_isCount; }; diff --git a/src/variables/variations/exclusion.h b/src/variables/variations/exclusion.h index 4f93e065..f50c7807 100644 --- a/src/variables/variations/exclusion.h +++ b/src/variables/variations/exclusion.h @@ -34,7 +34,8 @@ class Exclusion : public Variable { public: explicit Exclusion(Variable *v) : Variable(v->m_name), - var(v) { } + var(v) + { m_isExclusion = true; } std::list * evaluate(Assay *assay) override;