diff --git a/src/rule.cc b/src/rule.cc index f8cb476c..7d626757 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -257,9 +257,13 @@ bool Rule::evaluate(Assay *assay) { return evaluateActions(assay); } -#ifndef NO_LOGS std::string eparam = MacroExpansion::expand(this->op->param, assay); + std::string cache_key = eparam + this->op->op + Variable::to_s(variables) + std::to_string(rule_id); + if (RuleInstantCache::getInstance().count(cache_key) > 0) { + return 0; + } +#ifndef NO_LOGS if (this->op->param != eparam) { eparam = "\"" + eparam + "\" Was: \"" + this->op->param + "\""; } else { @@ -490,6 +494,11 @@ bool Rule::evaluate(Assay *assay) { } //delete e; } + + if (ret == 0) { + RuleInstantCache::getInstance().cache(cache_key); + } + return ret; } diff --git a/src/rule.h b/src/rule.h index a7a305a0..a256b4b6 100644 --- a/src/rule.h +++ b/src/rule.h @@ -29,6 +29,24 @@ namespace ModSecurity { +class RuleInstantCache : public std::unordered_map { + public: + static RuleInstantCache& getInstance() { + static RuleInstantCache instance; + return instance; + } + + void cache(const std::string& value) { + emplace(value, 1); + if (size() > 1500) { + erase(begin()); + } + } + private: + RuleInstantCache() {}; +}; + + class Rule { public: Rule(operators::Operator *_op,