Avoids string copy by working with pointers while resolving variables

This commit is contained in:
Felipe Zimmerle 2016-12-27 15:25:11 -03:00
parent 7834cf857b
commit a7f465cf3a
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
38 changed files with 179 additions and 94 deletions

View File

@ -33,11 +33,20 @@ namespace collection {
class Variable {
public:
Variable(const std::string& key, const std::string& value) :
Variable(const std::string *key, const std::string *value) :
m_key(key),
m_value(value) { }
std::string m_key;
std::string m_value;
m_value(value),
m_dynamic_value(false) { }
~Variable() {
if (m_dynamic_value) {
delete m_value;
}
}
const std::string *m_key;
const std::string *m_value;
bool m_dynamic_value;
};
} // namespace collection

View File

@ -56,7 +56,7 @@ class Rule {
void executeActionsAfterFullMatch(Transaction *trasn,
bool containsDisruptive, RuleMessage *ruleMessage);
std::vector<std::string> executeSecDefaultActionTransofrmations(
Transaction *trasn, std::string &value, bool multiMatch);
Transaction *trasn, const std::string &value, bool multiMatch);
bool executeOperatorAt(Transaction *trasn, std::string key,
std::string value);
void executeActionsIndependentOfChainedRuleResult(Transaction *trasn,

View File

@ -361,6 +361,19 @@ class Transaction {
RequestBodyProcessor::XML *m_xml;
RequestBodyProcessor::JSON *m_json;
std::string m_variableDuration;
std::map<std::string, std::string> m_variableEnvs;
std::string m_variableHighestSeverityAction;
std::string m_variableRemoteUser;
std::string m_variableTime;
std::string m_variableTimeDay;
std::string m_variableTimeEpoch;
std::string m_variableTimeHour;
std::string m_variableTimeMin;
std::string m_variableTimeSec;
std::string m_variableTimeWDay;
std::string m_variableTimeYear;
private:
std::string *m_ARGScombinedSizeStr;
std::string *m_namesArgs;

View File

@ -77,7 +77,7 @@ void InMemoryPerProcess::resolveSingleMatch(const std::string& var,
auto range = this->equal_range(var);
for (auto it = range.first; it != range.second; ++it) {
l->push_back(new Variable(var, it->second));
l->push_back(new Variable(&it->first, &it->second));
}
}
@ -90,7 +90,7 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var,
auto range = this->equal_range(var);
for (auto it = range.first; it != range.second; ++it) {
l->insert(l->begin(), new Variable(var, it->second));
l->insert(l->begin(), new Variable(&var, &it->second));
}
for (const auto& x : *this) {
@ -113,7 +113,7 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var,
continue;
}
l->insert(l->begin(), new Variable(x.first, x.second));
l->insert(l->begin(), new Variable(&x.first, &x.second));
}
}
@ -150,7 +150,7 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var,
continue;
}
l->insert(l->begin(), new Variable(x.first, x.second));
l->insert(l->begin(), new Variable(&x.first, &x.second));
}
}

View File

@ -282,10 +282,11 @@ bool Rule::executeOperatorAt(Transaction *trasn, std::string key,
// FIXME: this should be a list instead of a vector, keeping the but
// of v2 alive.
std::vector<std::string> Rule::executeSecDefaultActionTransofrmations(
Transaction *trasn, std::string &value, bool multiMatch) {
Transaction *trasn, const std::string &value2, bool multiMatch) {
int none = 0;
int transformations = 0;
std::vector<std::string> ret;
std::string value = std::string(value2);
if (multiMatch == true) {
ret.push_back(value);
@ -305,7 +306,7 @@ std::vector<std::string> Rule::executeSecDefaultActionTransofrmations(
for (Action *a : trasn->m_rules->defaultActions[this->phase]) {
if (a->action_kind \
== actions::Action::RunTimeBeforeMatchAttemptKind) {
std::string oldValue = value;
std::string oldValue = std::string(value);
if (multiMatch) {
oldValue = ret.back();
}
@ -330,7 +331,7 @@ std::vector<std::string> Rule::executeSecDefaultActionTransofrmations(
for (Action *a : this->m_actionsRuntimePre) {
if (none == 0) {
std::string oldValue = value;
std::string oldValue = std::string(value);
if (multiMatch) {
oldValue = ret.back();
}
@ -373,7 +374,7 @@ std::vector<std::string> Rule::executeSecDefaultActionTransofrmations(
std::vector<const collection::Variable *> Rule::getFinalVars(
Transaction *trasn) {
std::list<std::string> exclusions;
std::list<const std::string*> exclusions;
std::vector<Variable *> *variables = this->variables;
std::vector<const collection::Variable *> finalVars;
@ -386,7 +387,7 @@ std::vector<const collection::Variable *> Rule::getFinalVars(
exclusions.push_back(y->m_key);
delete y;
}
exclusions.push_back(variable->m_name);
exclusions.push_back(&variable->m_name);
}
}
@ -401,10 +402,13 @@ std::vector<const collection::Variable *> Rule::getFinalVars(
variable->evaluateInternal(trasn, this, &e);
for (const collection::Variable *v : e) {
if (std::find(exclusions.begin(), exclusions.end(),
v->m_key) != exclusions.end()) {
const std::string *key = v->m_key;
if (std::find_if(exclusions.begin(), exclusions.end(),
[key](const std::string *m) -> bool { return *key == *m; })
!= exclusions.end()) {
#ifndef NO_LOGS
trasn->debug(9, "Variable: " + v->m_key +
trasn->debug(9, "Variable: " + *key +
" is part of the exclusion list, skipping...");
#endif
continue;
@ -416,8 +420,8 @@ std::vector<const collection::Variable *> Rule::getFinalVars(
if (containsTag(tag, trasn) == false) {
continue;
}
if (args == v->m_key) {
trasn->debug(9, "Variable: " + v->m_key +
if (args == *key) {
trasn->debug(9, "Variable: " + *key +
" was excluded by ruleRemoteTargetByTag...");
ignoreVariable = true;
break;
@ -433,8 +437,8 @@ std::vector<const collection::Variable *> Rule::getFinalVars(
if (rule_id != id) {
continue;
}
if (args == v->m_key) {
trasn->debug(9, "Variable: " + v->m_key +
if (args == *key) {
trasn->debug(9, "Variable: " + *key +
" was excluded by ruleRemoteTargetById...");
ignoreVariable = true;
break;
@ -564,7 +568,9 @@ bool Rule::evaluate(Transaction *trasn) {
finalVars = getFinalVars(trasn);
for (const collection::Variable *v : finalVars) {
std::string value = v->m_value;
const std::string value = *(v->m_value);
const std::string key = *(v->m_key);
std::vector<std::string> values;
bool multiMatch = getActionsByName("multimatch").size() > 0;
@ -573,10 +579,11 @@ bool Rule::evaluate(Transaction *trasn) {
for (const std::string &valueTemp : values) {
bool ret;
ret = executeOperatorAt(trasn, v->m_key, valueTemp);
ret = executeOperatorAt(trasn, key, valueTemp);
if (ret == true) {
ruleMessage.m_match = resolveMatchMessage(v->m_key, value);
updateMatchedVars(trasn, v->m_key, value);
ruleMessage.m_match = resolveMatchMessage(key, value);
updateMatchedVars(trasn, key, value);
executeActionsIndependentOfChainedRuleResult(trasn,
&containsDisruptive, &ruleMessage);
globalRet = true;

View File

@ -80,6 +80,9 @@ void Rules::decrementReferenceCount(void) {
Rules::~Rules() {
int i = 0;
free(unicode_map_table);
unicode_map_table = NULL;
/** Cleanup the rules */
for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) {
std::vector<Rule *> rules = this->rules[i];
@ -97,9 +100,6 @@ Rules::~Rules() {
tmp->pop_back();
}
}
free(unicode_map_table);
}

View File

@ -768,8 +768,8 @@ int Transaction::processRequestBody() {
m_collections.resolveMultiMatches("REQUEST_HEADERS", &l);
for (auto &a : l) {
fullRequest = fullRequest + \
std::string(a->m_key, 16, a->m_key.length() - 16) + ": " \
+ a->m_value + "\n";
std::string(*a->m_key, 16, a->m_key->length() - 16) + ": " \
+ *a->m_value + "\n";
}
while (l.empty() == false) {
@ -1387,8 +1387,8 @@ std::string Transaction::toOldAuditLogFormat(int parts,
m_collections.m_transient->resolveMultiMatches("REQUEST_HEADERS", &l);
for (auto h : l) {
size_t pos = strlen("REQUEST_HEADERS:");
audit_log << h->m_key.c_str() + pos << ": ";
audit_log << h->m_value.c_str() << std::endl;
audit_log << h->m_key->c_str() + pos << ": ";
audit_log << h->m_value->c_str() << std::endl;
delete h;
}
audit_log << std::endl;
@ -1419,8 +1419,8 @@ std::string Transaction::toOldAuditLogFormat(int parts,
m_collections.m_transient->resolveMultiMatches("RESPONSE_HEADERS", &l);
for (auto h : l) {
size_t pos = strlen("RESPONSE_HEADERS:");
audit_log << h->m_key.c_str() + pos << ": ";
audit_log << h->m_value.c_str() << std::endl;
audit_log << h->m_key->c_str() + pos << ": ";
audit_log << h->m_value->c_str() << std::endl;
delete h;
}
}
@ -1516,7 +1516,7 @@ std::string Transaction::toJSON(int parts) {
m_collections.m_transient->resolveMultiMatches("REQUEST_HEADERS", &l);
for (auto h : l) {
size_t pos = strlen("REQUEST_HEADERS:");
LOGFY_ADD(h->m_key.c_str() + pos, h->m_value.c_str());
LOGFY_ADD(h->m_key->c_str() + pos, h->m_value->c_str());
delete h;
}
@ -1547,7 +1547,7 @@ std::string Transaction::toJSON(int parts) {
m_collections.m_transient->resolveMultiMatches("RESPONSE_HEADERS", &l);
for (auto h : l) {
size_t pos = strlen("RESPONSE_HEADERS:");
LOGFY_ADD(h->m_key.c_str() + pos, h->m_value.c_str());
LOGFY_ADD(h->m_key->c_str() + pos, h->m_value->c_str());
delete h;
}

View File

@ -29,13 +29,12 @@ namespace Variables {
void Duration::evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) {
std::string res;
double e = utils::cpu_seconds() - transaction->m_creationTimeStamp;
res = std::to_string(e);
transaction->m_variableDuration.assign(std::to_string(e));
l->push_back(new collection::Variable("DURATION", std::string(res)));
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableDuration));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class Duration : public Variable {
public:
explicit Duration(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("DURATION") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};

View File

@ -34,7 +34,6 @@ namespace Variables {
void Env::evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) {
std::map<std::string, std::string> envs;
for (char **current = environ; *current; current++) {
std::string env = std::string(*current);
size_t pos = env.find_first_of("=");
@ -43,20 +42,16 @@ void Env::evaluateInternal(Transaction *transaction,
}
std::string key = std::string(env, 0, pos);
std::string value = std::string(env, pos+1, env.length() - (pos + 1));
envs.insert(std::pair<std::string, std::string>("ENV:" + key, value));
if ("env:" + key == m_name) {
l->push_back(new collection::Variable(m_name, value));
return;
}
std::pair<std::string, std::string> a("ENV:" + key, value);
transaction->m_variableEnvs.insert(a);
}
for (auto& x : envs) {
for (auto& x : transaction->m_variableEnvs) {
if ((x.first.substr(0, m_name.size() + 1).compare(m_name + ":") != 0)
&& (x.first != m_name)) {
continue;
}
l->push_back(new collection::Variable(x.first, x.second));
l->push_back(new collection::Variable(&x.first, &x.second));
}
}

View File

@ -28,8 +28,10 @@ namespace Variables {
void HighestSeverity::evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) {
l->push_back(new collection::Variable("HIGHEST_SEVERITY",
std::to_string(transaction->m_highestSeverityAction)));
transaction->m_variableHighestSeverityAction.assign(
std::to_string(transaction->m_highestSeverityAction));
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableHighestSeverityAction));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class HighestSeverity : public Variable {
public:
explicit HighestSeverity(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("HIGHEST_SEVERITY") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};

View File

@ -15,27 +15,19 @@
#include "src/variables/modsec_build.h"
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <utility>
#include "modsecurity/transaction.h"
#include "modsecurity/modsecurity.h"
namespace modsecurity {
namespace Variables {
void ModsecBuild::evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) {
std::ostringstream ss;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_MAJOR;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_MINOR;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_PATCHLEVEL;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_TAG_NUM;
l->push_back(new collection::Variable("MODSEC_BUILD", ss.str()));
l->push_back(new collection::Variable(&m_retName, &m_build));
}

View File

@ -17,11 +17,13 @@
#include <string>
#include <list>
#include <utility>
#include <iostream>
#ifndef SRC_VARIABLES_MODSEC_BUILD_H_
#define SRC_VARIABLES_MODSEC_BUILD_H_
#include "src/variables/variable.h"
#include "modsecurity/modsecurity.h"
namespace modsecurity {
@ -31,10 +33,21 @@ namespace Variables {
class ModsecBuild : public Variable {
public:
explicit ModsecBuild(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("MODSEC_BUILD") {
std::ostringstream ss;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_MAJOR;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_MINOR;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_PATCHLEVEL;
ss << std::setw(2) << std::setfill('0') << MODSECURITY_TAG_NUM;
m_build = ss.str();
}
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_build;
std::string m_retName;
};

View File

@ -57,9 +57,10 @@ void RemoteUser::evaluateInternal(Transaction *transaction,
if (pos == std::string::npos) {
return;
}
base64 = std::string(base64, 0, pos);
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
l->push_back(new collection::Variable("REMOTE_USER", base64));
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableRemoteUser));
}

View File

@ -33,10 +33,12 @@ namespace Variables {
class RemoteUser : public Variable {
public:
explicit RemoteUser(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("REMOTE_USER") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};

View File

@ -46,7 +46,9 @@ void Time::evaluateInternal(Transaction *transaction,
localtime_r(&timer, &timeinfo);
strftime(tstr, 200, "%H:%M:%S", &timeinfo);
l->push_back(new collection::Variable("TIME", std::string(tstr)));
transaction->m_variableTime.assign(tstr);
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTime));
}

View File

@ -32,10 +32,12 @@ namespace Variables {
class Time : public Variable {
public:
explicit Time(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -45,7 +45,10 @@ void TimeDay::evaluateInternal(Transaction *transaction,
localtime_r(&timer, &timeinfo);
strftime(tstr, 200, "%d", &timeinfo);
l->push_back(new collection::Variable("TIME_DAY", std::string(tstr)));
transaction->m_variableTimeDay.assign(tstr);
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeDay));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeDay : public Variable {
public:
explicit TimeDay(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_DAY") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -35,8 +35,10 @@ namespace Variables {
void TimeEpoch::evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) {
l->push_back(new collection::Variable("TIME_EPOCH",
std::to_string(std::time(nullptr))));
transaction->m_variableTimeEpoch.assign(
std::to_string(std::time(nullptr)));
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeEpoch));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeEpoch : public Variable {
public:
explicit TimeEpoch(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_EPOCH") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -45,7 +45,10 @@ void TimeHour::evaluateInternal(Transaction *transaction,
localtime_r(&timer, &timeinfo);
strftime(tstr, 200, "%H", &timeinfo);
l->push_back(new collection::Variable("TIME_HOUR", std::string(tstr)));
transaction->m_variableTimeHour.assign(tstr);
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeHour));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeHour : public Variable {
public:
explicit TimeHour(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_HOUR") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -45,7 +45,10 @@ void TimeMin::evaluateInternal(Transaction *transaction,
localtime_r(&timer, &timeinfo);
strftime(tstr, 200, "%M", &timeinfo);
l->push_back(new collection::Variable("TIME_MIN", std::string(tstr)));
transaction->m_variableTimeMin.assign(tstr);
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeMin));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeMin : public Variable {
public:
explicit TimeMin(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_MIN") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -47,7 +47,10 @@ void TimeMon::evaluateInternal(Transaction *transaction,
int a = atoi(tstr);
a--;
l->push_back(new collection::Variable("TIME_MON", std::to_string(a)));
transaction->m_variableTimeMin.assign(std::to_string(a));
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeMin));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeMon : public Variable {
public:
explicit TimeMon(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_MON") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -45,7 +45,10 @@ void TimeSec::evaluateInternal(Transaction *transaction,
localtime_r(&timer, &timeinfo);
strftime(tstr, 200, "%S", &timeinfo);
l->push_back(new collection::Variable("TIME_SEC", std::string(tstr)));
transaction->m_variableTimeSec.assign(tstr);
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeSec));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeSec : public Variable {
public:
explicit TimeSec(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_SEC") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -47,7 +47,10 @@ void TimeWDay::evaluateInternal(Transaction *transaction,
int a = atoi(tstr);
a--;
l->push_back(new collection::Variable("TIME_WDAY", std::to_string(a)));
transaction->m_variableTimeWDay.assign(tstr);
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeWDay));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeWDay : public Variable {
public:
explicit TimeWDay(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_WDAY") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -45,7 +45,10 @@ void TimeYear::evaluateInternal(Transaction *transaction,
localtime_r(&timer, &timeinfo);
strftime(tstr, 200, "%Y", &timeinfo);
l->push_back(new collection::Variable("TIME_YEAR", std::string(tstr)));
transaction->m_variableTimeYear.assign(tstr);
l->push_back(new collection::Variable(&m_retName,
&transaction->m_variableTimeYear));
}

View File

@ -31,10 +31,12 @@ namespace Variables {
class TimeYear : public Variable {
public:
explicit TimeYear(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_retName("TIME_YEAR") { }
void evaluateInternal(Transaction *transaction,
std::vector<const collection::Variable *> *l) override;
std::string m_retName;
};
} // namespace Variables

View File

@ -46,10 +46,13 @@ void Count::evaluateInternal(Transaction *transaction,
}
delete reslIn;
std::string res = std::to_string(count);
std::string *res = new std::string(std::to_string(count));
l->push_back(new collection::Variable(std::string(var->m_name),
std::string(res)));
collection::Variable *val = new collection::Variable(&var->m_name,
res);
val->m_dynamic_value = true;
l->push_back(val);
}

View File

@ -73,8 +73,7 @@ void XML::evaluateInternal(Transaction *t,
/* Invocation without an XPath expression makes sense
* with functions that manipulate the document tree.
*/
l->push_back(new collection::Variable("XML",
std::string("[XML document tree]" + param)));
l->push_back(new collection::Variable(&m_name, &m_plain));
return;
}
@ -124,8 +123,9 @@ void XML::evaluateInternal(Transaction *t,
content = reinterpret_cast<char *>(
xmlNodeGetContent(nodes->nodeTab[i]));
if (content != NULL) {
l->push_back(new collection::Variable(m_name,
std::string(content)));
// FIXME: Memory leak
l->push_back(new collection::Variable(&m_name,
new std::string(content)));
xmlFree(content);
}
}

View File

@ -33,11 +33,13 @@ namespace Variables {
class XML : public Variable {
public:
explicit XML(std::string _name)
: Variable(_name) { }
: Variable(_name),
m_plain("[XML document tree]") { }
void evaluateInternal(Transaction *transaction,
Rule *rule,
std::vector<const collection::Variable *> *l) override;
std::string m_plain;
};
} // namespace Variables

View File

@ -256,7 +256,7 @@
]
},
"expected":{
"debug_log":" Target value: \"message123\" \\(Variable: rule:msg\\)"
"debug_log":" Target value: \"message123\" \\(Variable: RULE:msg\\)"
},
"rules":[
"SecRuleEngine On",