mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-30 03:34:29 +03:00
perf. improvement/rx: Only compute dynamic regex in case of macro
On #1528 was added the support for macro expansion on @rx operator. The performance improvement suggested on the pull request was not thread safe, therefore removed. This patch adds a performance improvement on top of #1528. The benchmarks points to 10x faster results on OWASP CRS.
This commit is contained in:
@@ -48,8 +48,20 @@ std::string MacroExpansion::expand(const std::string& input,
|
||||
}
|
||||
|
||||
|
||||
bool MacroExpansion::containsMacro(std::string& input) {
|
||||
size_t pos = input.find("%{");
|
||||
size_t end = input.find("}");
|
||||
|
||||
if (pos == std::string::npos || end == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string MacroExpansion::expand(const std::string& input,
|
||||
modsecurity::Rule *rule, Transaction *transaction) {
|
||||
modsecurity::Rule *rule, Transaction *transaction) {
|
||||
std::string res;
|
||||
size_t pos = input.find("%{");
|
||||
|
||||
|
@@ -47,6 +47,8 @@ class MacroExpansion {
|
||||
return toupper(aa) == bb;
|
||||
});
|
||||
}
|
||||
|
||||
static bool containsMacro(std::string& input);
|
||||
};
|
||||
|
||||
|
||||
|
@@ -28,6 +28,15 @@ namespace modsecurity {
|
||||
namespace operators {
|
||||
|
||||
|
||||
bool Rx::init(const std::string &arg, std::string *error) {
|
||||
m_containsMacro = MacroExpansion::containsMacro(m_param);
|
||||
if (m_containsMacro == false) {
|
||||
m_re = new Regex(m_param);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Rx::evaluate(Transaction *transaction, Rule *rule,
|
||||
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) {
|
||||
@@ -39,8 +48,12 @@ bool Rx::evaluate(Transaction *transaction, Rule *rule,
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string eparam = MacroExpansion::expand(m_param, transaction);
|
||||
re = new Regex(eparam);
|
||||
if (m_containsMacro) {
|
||||
std::string eparam = MacroExpansion::expand(m_param, transaction);
|
||||
re = new Regex(eparam);
|
||||
} else {
|
||||
re = m_re;
|
||||
}
|
||||
|
||||
matches = re->searchAll(input);
|
||||
if (rule && rule->getActionsByName("capture").size() > 0 && transaction) {
|
||||
@@ -62,7 +75,9 @@ bool Rx::evaluate(Transaction *transaction, Rule *rule,
|
||||
logOffset(ruleMessage, i.m_offset, i.m_length);
|
||||
}
|
||||
|
||||
delete re;
|
||||
if (m_containsMacro) {
|
||||
delete re;
|
||||
}
|
||||
|
||||
if (matches.size() > 0) {
|
||||
return true;
|
||||
|
@@ -36,17 +36,25 @@ class Rx : public Operator {
|
||||
public:
|
||||
/** @ingroup ModSecurity_Operator */
|
||||
Rx(std::string op, std::string param, bool negation)
|
||||
: Operator(op, param, negation) {
|
||||
: Operator(op, param, negation),
|
||||
m_containsMacro(false) {
|
||||
}
|
||||
Rx(std::string name, std::string param)
|
||||
: Operator(name, param) {
|
||||
: Operator(name, param),
|
||||
m_containsMacro(false) {
|
||||
}
|
||||
explicit Rx(std::string param)
|
||||
: Operator("Rx", param) {
|
||||
: Operator("Rx", param),
|
||||
m_containsMacro(false) {
|
||||
}
|
||||
|
||||
~Rx() {
|
||||
if (m_containsMacro == false && m_re != NULL) {
|
||||
delete m_re;
|
||||
m_re = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool evaluate(Transaction *transaction, Rule *rule,
|
||||
const std::string &input) override {
|
||||
return evaluate(transaction, NULL, input, NULL);
|
||||
@@ -58,6 +66,11 @@ class Rx : public Operator {
|
||||
bool evaluate(Transaction *transaction, Rule *rule,
|
||||
const std::string& input,
|
||||
std::shared_ptr<RuleMessage> ruleMessage) override;
|
||||
|
||||
bool init(const std::string &arg, std::string *error);
|
||||
private:
|
||||
bool m_containsMacro;
|
||||
Regex *m_re;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -1027,6 +1027,11 @@ op_before_init:
|
||||
| OPERATOR_RX FREE_TEXT
|
||||
{
|
||||
OPERATOR_CONTAINER($$, new operators::Rx($2));
|
||||
std::string error;
|
||||
if ($$->init(driver.ref.back(), &error) == false) {
|
||||
driver.error(@0, error);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| OPERATOR_STR_EQ FREE_TEXT
|
||||
{
|
||||
|
Reference in New Issue
Block a user