mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-30 11:44:32 +03:00
Improve performance of VariableOrigin instances
- The previous approach would create a std::unique_ptr and store it in a std::list in VariableValue (Origins) - The new approach now stores Origins in a std::vector and constructs VariableOrigin elements in-place on insertion. - Instead of having two heap-allocations for every added VariableOrigin instance, this performs only one. - If multiple origins are added, std::vector's growth strategy may even prevent a heap-allocation. There's a cost on growing the size of the vector, because a copy of current elements will be necessary. - Introduced reserveOrigin method to notify that multiple insertions will be made, so that we can use std::vector's reserve and do a single allocation (and copy of previous elements), and then just initialize the new elements in-place.
This commit is contained in:
@@ -52,26 +52,16 @@ void AnchoredSetVariable::unset() {
|
||||
|
||||
void AnchoredSetVariable::set(const std::string &key,
|
||||
const std::string &value, size_t offset, size_t len) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
VariableValue *var = new VariableValue(&m_name, &key, &value);
|
||||
|
||||
origin->m_offset = offset;
|
||||
origin->m_length = len;
|
||||
|
||||
var->addOrigin(std::move(origin));
|
||||
var->addOrigin(len, offset);
|
||||
emplace(key, var);
|
||||
}
|
||||
|
||||
|
||||
void AnchoredSetVariable::set(const std::string &key,
|
||||
const std::string &value, size_t offset) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
VariableValue *var = new VariableValue(&m_name, &key, &value);
|
||||
|
||||
origin->m_offset = offset;
|
||||
origin->m_length = value.size();
|
||||
|
||||
var->addOrigin(std::move(origin));
|
||||
var->addOrigin(value.size(), offset);
|
||||
emplace(key, var);
|
||||
}
|
||||
|
||||
|
@@ -54,58 +54,40 @@ void AnchoredVariable::unset() {
|
||||
|
||||
void AnchoredVariable::set(const std::string &a, size_t offset,
|
||||
size_t offsetLen) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
|
||||
m_offset = offset;
|
||||
m_value.assign(a.c_str(), a.size());
|
||||
origin->m_offset = offset;
|
||||
origin->m_length = offsetLen;
|
||||
m_var->addOrigin(std::move(origin));
|
||||
m_var->addOrigin(offsetLen, offset);
|
||||
}
|
||||
|
||||
|
||||
void AnchoredVariable::set(const std::string &a, size_t offset) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
|
||||
m_offset = offset;
|
||||
m_value.assign(a.c_str(), a.size());
|
||||
origin->m_offset = offset;
|
||||
origin->m_length = m_value.size();
|
||||
m_var->addOrigin(std::move(origin));
|
||||
m_var->addOrigin(m_value.size(), offset);
|
||||
}
|
||||
|
||||
|
||||
void AnchoredVariable::append(const std::string &a, size_t offset,
|
||||
bool spaceSeparator) {
|
||||
std::unique_ptr<VariableOrigin> origin(
|
||||
new VariableOrigin());
|
||||
|
||||
if (spaceSeparator && !m_value.empty()) {
|
||||
m_value.append(" " + a);
|
||||
} else {
|
||||
m_value.append(a);
|
||||
}
|
||||
m_offset = offset;
|
||||
origin->m_offset = offset;
|
||||
origin->m_length = a.size();
|
||||
m_var->addOrigin(std::move(origin));
|
||||
m_var->addOrigin(a.size(), offset);
|
||||
}
|
||||
|
||||
|
||||
void AnchoredVariable::append(const std::string &a, size_t offset,
|
||||
bool spaceSeparator, int size) {
|
||||
std::unique_ptr<VariableOrigin> origin(
|
||||
new VariableOrigin());
|
||||
|
||||
bool spaceSeparator, size_t size) {
|
||||
if (spaceSeparator && !m_value.empty()) {
|
||||
m_value.append(" " + a);
|
||||
} else {
|
||||
m_value.append(a);
|
||||
}
|
||||
m_offset = offset;
|
||||
origin->m_offset = offset;
|
||||
origin->m_length = size;
|
||||
m_var->addOrigin(std::move(origin));
|
||||
m_var->addOrigin({size, offset});
|
||||
}
|
||||
|
||||
|
||||
|
@@ -317,8 +317,8 @@ bool RuleWithOperator::evaluate(Transaction *trans,
|
||||
if (ret == true) {
|
||||
ruleMessage->m_match = m_operator->resolveMatchMessage(trans,
|
||||
key, value);
|
||||
for (auto &i : v->getOrigin()) {
|
||||
ruleMessage->m_reference.append(i->toText());
|
||||
for (const auto &i : v->getOrigin()) {
|
||||
ruleMessage->m_reference.append(i.toText());
|
||||
}
|
||||
|
||||
ruleMessage->m_reference.append(*valueTemp.second);
|
||||
|
@@ -39,50 +39,41 @@ namespace variables {
|
||||
void RemoteUser::evaluate(Transaction *transaction,
|
||||
RuleWithActions *rule,
|
||||
std::vector<const VariableValue *> *l) {
|
||||
size_t pos;
|
||||
std::string base64;
|
||||
VariableValue *var;
|
||||
std::string header;
|
||||
std::vector<const VariableValue *> l2;
|
||||
|
||||
std::vector<const VariableValue *> *l2 = \
|
||||
new std::vector<const VariableValue *>();
|
||||
transaction->m_variableRequestHeaders.resolve("authorization", l2);
|
||||
transaction->m_variableRequestHeaders.resolve("authorization", &l2);
|
||||
|
||||
if (l2->size() < 1) {
|
||||
goto clear;
|
||||
if (!l2.empty()) {
|
||||
const auto *v = l2[0];
|
||||
|
||||
const auto &header = v->getValue();
|
||||
|
||||
std::string base64;
|
||||
|
||||
if (header.compare(0, 6, "Basic ") == 0) {
|
||||
base64 = std::string(header, 6, header.length());
|
||||
}
|
||||
|
||||
base64 = Utils::Base64::decode(base64);
|
||||
|
||||
const auto pos = base64.find(":");
|
||||
if (pos != std::string::npos) {
|
||||
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
|
||||
|
||||
auto var = std::make_unique<VariableValue>(&v->getKeyWithCollection(),
|
||||
&transaction->m_variableRemoteUser);
|
||||
|
||||
var->reserveOrigin(v->getOrigin().size());
|
||||
for (const auto &i : v->getOrigin()) {
|
||||
var->addOrigin(i);
|
||||
}
|
||||
l->push_back(var.release());
|
||||
}
|
||||
|
||||
for (auto &a : l2) {
|
||||
delete a;
|
||||
}
|
||||
}
|
||||
|
||||
header = std::string(l2->at(0)->getValue());
|
||||
|
||||
if (header.compare(0, 6, "Basic ") == 0) {
|
||||
base64 = std::string(header, 6, header.length());
|
||||
}
|
||||
|
||||
base64 = Utils::Base64::decode(base64);
|
||||
|
||||
pos = base64.find(":");
|
||||
if (pos == std::string::npos) {
|
||||
goto clear;
|
||||
}
|
||||
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
|
||||
|
||||
var = new VariableValue(&l2->at(0)->getKeyWithCollection(),
|
||||
&transaction->m_variableRemoteUser);
|
||||
|
||||
for (const auto &i : l2->at(0)->getOrigin()) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
origin->m_offset = i->m_offset;
|
||||
origin->m_length = i->m_length;
|
||||
var->addOrigin(std::move(origin));
|
||||
}
|
||||
l->push_back(var);
|
||||
|
||||
clear:
|
||||
for (auto &a : *l2) {
|
||||
delete a;
|
||||
}
|
||||
l2->clear();
|
||||
delete l2;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -49,15 +49,12 @@ class Rule_DictElement : public VariableDictElement { \
|
||||
if (!r || r->m_ruleId == 0) {
|
||||
return;
|
||||
}
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
std::string *a = new std::string(std::to_string(r->m_ruleId));
|
||||
VariableValue *var = new VariableValue(&m_rule, &m_rule_id,
|
||||
a
|
||||
);
|
||||
delete a;
|
||||
origin->m_offset = 0;
|
||||
origin->m_length = 0;
|
||||
var->addOrigin(std::move(origin));
|
||||
var->addOrigin();
|
||||
l->push_back(var);
|
||||
}
|
||||
|
||||
@@ -75,15 +72,12 @@ class Rule_DictElement : public VariableDictElement { \
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
std::string *a = new std::string(r->m_rev);
|
||||
VariableValue *var = new VariableValue(&m_rule, &m_rule_rev,
|
||||
a
|
||||
);
|
||||
delete a;
|
||||
origin->m_offset = 0;
|
||||
origin->m_length = 0;
|
||||
var->addOrigin(std::move(origin));
|
||||
var->addOrigin();
|
||||
l->push_back(var);
|
||||
}
|
||||
|
||||
@@ -98,15 +92,12 @@ class Rule_DictElement : public VariableDictElement { \
|
||||
}
|
||||
|
||||
if (r && r->hasSeverity()) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
std::string *a = new std::string(std::to_string(r->severity()));
|
||||
VariableValue *var = new VariableValue(&m_rule, &m_rule_severity,
|
||||
a
|
||||
);
|
||||
delete a;
|
||||
origin->m_offset = 0;
|
||||
origin->m_length = 0;
|
||||
var->addOrigin(std::move(origin));
|
||||
var->addOrigin();
|
||||
l->push_back(var);
|
||||
}
|
||||
}
|
||||
@@ -122,15 +113,12 @@ class Rule_DictElement : public VariableDictElement { \
|
||||
}
|
||||
|
||||
if (r && r->hasLogData()) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
std::string *a = new std::string(r->logData(t));
|
||||
VariableValue *var = new VariableValue(&m_rule, &m_rule_logdata,
|
||||
a
|
||||
);
|
||||
delete a;
|
||||
origin->m_offset = 0;
|
||||
origin->m_length = 0;
|
||||
var->addOrigin(std::move(origin));
|
||||
var->addOrigin();
|
||||
l->push_back(var);
|
||||
}
|
||||
}
|
||||
@@ -145,15 +133,12 @@ class Rule_DictElement : public VariableDictElement { \
|
||||
}
|
||||
|
||||
if (r && r->hasMsg()) {
|
||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||
std::string *a = new std::string(r->msg(t));
|
||||
VariableValue *var = new VariableValue(&m_rule, &m_rule_msg,
|
||||
a
|
||||
);
|
||||
delete a;
|
||||
origin->m_offset = 0;
|
||||
origin->m_length = 0;
|
||||
var->addOrigin(std::move(origin));
|
||||
var->addOrigin();
|
||||
l->push_back(var);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user