Fix memory issues while resolving variables

This commit is contained in:
Felipe Zimmerle 2017-08-27 19:00:30 -03:00
parent 003a8e8e5f
commit 7ac6bf7241
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
10 changed files with 116 additions and 117 deletions

View File

@ -58,10 +58,12 @@ class AnchoredVariable {
std::unique_ptr<std::string> resolveFirst(); std::unique_ptr<std::string> resolveFirst();
Transaction *m_transaction; Transaction *m_transaction;
collection::Variable *m_var;
int m_offset; int m_offset;
std::string m_name; std::string m_name;
std::string m_value; std::string m_value;
private:
collection::Variable *m_var;
}; };
} // namespace modsecurity } // namespace modsecurity

View File

@ -37,32 +37,36 @@ namespace collection {
class Variable { class Variable {
public: public:
explicit Variable(const std::string *key) : explicit Variable(const std::string *key) :
m_dynamic(true) { m_key(""),
m_key.reset(new std::string(*key)); m_value("") {
m_key.assign(*key);
} }
Variable(const std::string *key, const std::string *value) : Variable(const std::string *key, const std::string *value) :
m_dynamic(true) { m_key(""),
m_key.reset(new std::string(*key)); m_value("") {
m_value.reset(new std::string(*value)); m_key.assign(*key);
m_value.assign(*value);
}
Variable() :
m_key(""),
m_value("") { }
Variable(const Variable *o) :
m_key(""),
m_value("") {
m_key.assign(o->m_key);
m_value.assign(o->m_value);
for (auto &i : o->m_orign) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
origin->m_offset = i->m_offset;
origin->m_length = i->m_length;
m_orign.push_back(std::move(origin));
} }
explicit Variable(const std::shared_ptr<std::string> key) :
m_dynamic(true) {
m_key = key;
}
Variable(std::shared_ptr<std::string> key, std::shared_ptr<std::string> value) :
m_dynamic(true) {
m_key = key;
m_value = value;
}
~Variable() {
} }
std::shared_ptr<std::string> m_key; std::string m_key;
std::shared_ptr<std::string> m_value; std::string m_value;
std::list<std::unique_ptr<VariableOrigin>> m_orign; std::list<std::unique_ptr<VariableOrigin>> m_orign;
bool m_dynamic;
}; };
} // namespace collection } // namespace collection

View File

@ -55,11 +55,12 @@ void AnchoredSetVariable::set(const std::string &key,
std::string *v = new std::string(value); std::string *v = new std::string(value);
std::string *k = new std::string(m_name + ":" + key); std::string *k = new std::string(m_name + ":" + key);
collection::Variable *var = new collection::Variable(k, v); collection::Variable *var = new collection::Variable(k, v);
delete v;
delete k;
origin->m_offset = offset; origin->m_offset = offset;
origin->m_length = len; origin->m_length = len;
var->m_dynamic = false;
var->m_orign.push_back(std::move(origin)); var->m_orign.push_back(std::move(origin));
emplace(key, var); emplace(key, var);
} }
@ -71,11 +72,12 @@ void AnchoredSetVariable::set(const std::string &key,
std::string *v = new std::string(value); std::string *v = new std::string(value);
std::string *k = new std::string(m_name + ":" + key); std::string *k = new std::string(m_name + ":" + key);
collection::Variable *var = new collection::Variable(k, v); collection::Variable *var = new collection::Variable(k, v);
delete v;
delete k;
origin->m_offset = offset; origin->m_offset = offset;
origin->m_length = value.size(); origin->m_length = value.size();
var->m_dynamic = false;
var->m_orign.push_back(std::move(origin)); var->m_orign.push_back(std::move(origin));
emplace(key, var); emplace(key, var);
} }
@ -84,7 +86,7 @@ void AnchoredSetVariable::set(const std::string &key,
void AnchoredSetVariable::resolve( void AnchoredSetVariable::resolve(
std::vector<const collection::Variable *> *l) { std::vector<const collection::Variable *> *l) {
for (const auto& x : *this) { for (const auto& x : *this) {
l->insert(l->begin(), x.second); l->insert(l->begin(), new collection::Variable(x.second));
} }
} }
@ -93,7 +95,7 @@ void AnchoredSetVariable::resolve(const std::string &key,
std::vector<const collection::Variable *> *l) { std::vector<const collection::Variable *> *l) {
auto range = this->equal_range(key); auto range = this->equal_range(key);
for (auto it = range.first; it != range.second; ++it) { for (auto it = range.first; it != range.second; ++it) {
l->push_back(it->second); l->push_back(new collection::Variable(it->second));
} }
} }
@ -103,7 +105,7 @@ std::unique_ptr<std::string> AnchoredSetVariable::resolveFirst(
auto range = equal_range(key); auto range = equal_range(key);
for (auto it = range.first; it != range.second; ++it) { for (auto it = range.first; it != range.second; ++it) {
std::unique_ptr<std::string> b(new std::string()); std::unique_ptr<std::string> b(new std::string());
b->assign(*it->second->m_value); b->assign(it->second->m_value);
return b; return b;
} }
return nullptr; return nullptr;
@ -117,7 +119,7 @@ void AnchoredSetVariable::resolveRegularExpression(Utils::Regex *r,
if (ret <= 0) { if (ret <= 0) {
continue; continue;
} }
l->insert(l->begin(), x.second); l->insert(l->begin(), new collection::Variable(x.second));
} }
} }

View File

@ -37,24 +37,19 @@ AnchoredVariable::AnchoredVariable(Transaction *t,
m_value("") { m_value("") {
m_name.append(name); m_name.append(name);
m_var = new collection::Variable(&m_name); m_var = new collection::Variable(&m_name);
m_var->m_dynamic = false;
m_var->m_value.reset(&m_value);
} }
AnchoredVariable::~AnchoredVariable() { AnchoredVariable::~AnchoredVariable() {
/*
if (m_var) { if (m_var) {
delete (m_var); delete (m_var);
m_var = NULL; m_var = NULL;
} }
*/
} }
void AnchoredVariable::unset() { void AnchoredVariable::unset() {
m_value.clear(); m_value.clear();
m_var->m_orign.clear();
} }
@ -116,11 +111,13 @@ void AnchoredVariable::append(const std::string &a, size_t offset,
void AnchoredVariable::evaluate(std::vector<const collection::Variable *> *l) { void AnchoredVariable::evaluate(std::vector<const collection::Variable *> *l) {
if (m_name.empty() || m_var == NULL || m_var->m_key == NULL if (m_name.empty() or m_value.empty()) {
|| m_var->m_value == NULL || m_var->m_key->empty()) {
return; return;
} }
l->push_back(m_var);
m_var->m_value.assign(m_value);
collection::Variable *m_var2 = new collection::Variable(m_var);
l->push_back(m_var2);
} }

View File

@ -431,9 +431,9 @@ std::list<std::pair<std::shared_ptr<std::string>,
std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars( std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
Transaction *trans) { Transaction *trans) {
std::list<std::shared_ptr<std::string>> exclusions; std::list<std::string> exclusions;
std::list<std::shared_ptr<std::string>> exclusions_update_by_tag_remove; std::list<std::string> exclusions_update_by_tag_remove;
std::list<std::shared_ptr<std::string>> exclusions_update_by_id_remove; std::list<std::string> exclusions_update_by_id_remove;
std::vector<Variables::Variable *> variables; std::vector<Variables::Variable *> variables;
std::vector<std::unique_ptr<collection::Variable>> finalVars; std::vector<std::unique_ptr<collection::Variable>> finalVars;
@ -448,8 +448,9 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
a.second->evaluateInternal(trans, this, &z); a.second->evaluateInternal(trans, this, &z);
for (auto &y : z) { for (auto &y : z) {
exclusions_update_by_tag_remove.push_back(y->m_key); exclusions_update_by_tag_remove.push_back(y->m_key);
delete y;
} }
exclusions_update_by_tag_remove.push_back(std::make_shared<std::string>(a.second->m_name)); exclusions_update_by_tag_remove.push_back(a.second->m_name);
} else { } else {
Variable *b = a.second.get(); Variable *b = a.second.get();
@ -466,8 +467,9 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
a.second->evaluateInternal(trans, this, &z); a.second->evaluateInternal(trans, this, &z);
for (auto &y : z) { for (auto &y : z) {
exclusions_update_by_id_remove.push_back(y->m_key); exclusions_update_by_id_remove.push_back(y->m_key);
delete y;
} }
exclusions_update_by_id_remove.push_back(std::make_shared<std::string>(a.second->m_name)); exclusions_update_by_id_remove.push_back(a.second->m_name);
} else { } else {
Variable *b = a.second.get(); Variable *b = a.second.get();
variables.push_back(b); variables.push_back(b);
@ -481,8 +483,9 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
variable->evaluateInternal(trans, this, &z); variable->evaluateInternal(trans, this, &z);
for (auto &y : z) { for (auto &y : z) {
exclusions.push_back(y->m_key); exclusions.push_back(y->m_key);
delete y;
} }
// exclusions.push_back(std::make_shared<std::string>(&variable->m_name)); exclusions.push_back(variable->m_name);
} }
} }
@ -497,73 +500,68 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
variable->evaluateInternal(trans, this, &e); variable->evaluateInternal(trans, this, &e);
for (const collection::Variable *v : e) { for (const collection::Variable *v : e) {
const std::shared_ptr<std::string> key = v->m_key; std::string key = v->m_key;
if (std::find_if(exclusions.begin(), exclusions.end(), if (std::find_if(exclusions.begin(), exclusions.end(),
[key](std::shared_ptr<std::string> m) -> bool { return *key == *m.get(); }) [key](std::string m) -> bool { return key == m; })
!= exclusions.end()) { != exclusions.end()) {
#ifndef NO_LOGS #ifndef NO_LOGS
trans->debug(9, "Variable: " + *key + trans->debug(9, "Variable: " + key +
" is part of the exclusion list, skipping..."); " is part of the exclusion list, skipping...");
#endif #endif
if (v->m_dynamic) {
delete v; delete v;
v = NULL; v = NULL;
}
continue; continue;
} }
if (std::find_if(exclusions_update_by_tag_remove.begin(), if (std::find_if(exclusions_update_by_tag_remove.begin(),
exclusions_update_by_tag_remove.end(), exclusions_update_by_tag_remove.end(),
[key](std::shared_ptr<std::string> m) -> bool { return *key == *m.get(); }) [key](std::string m) -> bool { return key == m; })
!= exclusions_update_by_tag_remove.end()) { != exclusions_update_by_tag_remove.end()) {
#ifndef NO_LOGS #ifndef NO_LOGS
trans->debug(9, "Variable: " + *key + trans->debug(9, "Variable: " + key +
" is part of the exclusion list (from update by tag" + " is part of the exclusion list (from update by tag" +
"), skipping..."); "), skipping...");
#endif #endif
if (v->m_dynamic) {
delete v; delete v;
v = NULL; v = NULL;
}
continue; continue;
} }
if (std::find_if(exclusions_update_by_id_remove.begin(), if (std::find_if(exclusions_update_by_id_remove.begin(),
exclusions_update_by_id_remove.end(), exclusions_update_by_id_remove.end(),
[key](std::shared_ptr<std::string> m) -> bool { return *key == *m.get(); }) [key](std::string m) -> bool { return key == m; })
!= exclusions_update_by_id_remove.end()) { != exclusions_update_by_id_remove.end()) {
#ifndef NO_LOGS #ifndef NO_LOGS
trans->debug(9, "Variable: " + *key + trans->debug(9, "Variable: " + key +
" is part of the exclusion list (from update by ID), skipping..."); " is part of the exclusion list (from update by ID), skipping...");
#endif #endif
if (v->m_dynamic) {
delete v; delete v;
v = NULL; v = NULL;
}
continue; continue;
} }
for (auto &i : trans->m_ruleRemoveTargetByTag) { for (auto &i : trans->m_ruleRemoveTargetByTag) {
std::string tag = i.first; std::string tag = i.first;
std::string args = i.second; std::string args = i.second;
size_t posa = key->find(":"); size_t posa = key.find(":");
if (containsTag(tag, trans) == false) { if (containsTag(tag, trans) == false) {
continue; continue;
} }
if (args == *key) { if (args == key) {
#ifndef NO_LOGS #ifndef NO_LOGS
trans->debug(9, "Variable: " + *key + trans->debug(9, "Variable: " + key +
" was excluded by ruleRemoteTargetByTag..."); " was excluded by ruleRemoteTargetByTag...");
#endif #endif
ignoreVariable = true; ignoreVariable = true;
break; break;
} }
if (posa != std::string::npos) { if (posa != std::string::npos) {
std::string var = std::string(*key, posa); std::string var = std::string(key, posa);
if (var == args) { if (var == args) {
#ifndef NO_LOGS #ifndef NO_LOGS
trans->debug(9, "Variable: " + *key + trans->debug(9, "Variable: " + key +
" was excluded by ruleRemoteTargetByTag..."); " was excluded by ruleRemoteTargetByTag...");
#endif #endif
ignoreVariable = true; ignoreVariable = true;
@ -572,33 +570,31 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
} }
} }
if (ignoreVariable) { if (ignoreVariable) {
if (v->m_dynamic) {
delete v; delete v;
v = NULL; v = NULL;
}
continue; continue;
} }
for (auto &i : trans->m_ruleRemoveTargetById) { for (auto &i : trans->m_ruleRemoveTargetById) {
int id = i.first; int id = i.first;
std::string args = i.second; std::string args = i.second;
size_t posa = key->find(":"); size_t posa = key.find(":");
if (m_ruleId != id) { if (m_ruleId != id) {
continue; continue;
} }
if (args == *key) { if (args == key) {
#ifndef NO_LOGS #ifndef NO_LOGS
trans->debug(9, "Variable: " + *key + trans->debug(9, "Variable: " + key +
" was excluded by ruleRemoveTargetById..."); " was excluded by ruleRemoveTargetById...");
#endif #endif
ignoreVariable = true; ignoreVariable = true;
break; break;
} }
if (posa != std::string::npos) { if (posa != std::string::npos) {
if (key->size() > posa) { if (key.size() > posa) {
std::string var = std::string(*key, 0, posa); std::string var = std::string(key, 0, posa);
if (var == args) { if (var == args) {
#ifndef NO_LOGS #ifndef NO_LOGS
trans->debug(9, "Variable: " + var + trans->debug(9, "Variable: " + var +
@ -611,27 +607,14 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
} }
} }
if (ignoreVariable) { if (ignoreVariable) {
if (v->m_dynamic) {
delete v; delete v;
v = NULL; v = NULL;
}
continue; continue;
} }
std::unique_ptr<collection::Variable> var(new collection::Variable( std::unique_ptr<collection::Variable> var(new collection::Variable(v));
new std::string(*v->m_key), delete v;
new std::string(*v->m_value))); v = NULL;
for (auto &i : v->m_orign) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
origin->m_offset = i->m_offset;
origin->m_length = i->m_length;
var->m_orign.push_back(std::move(origin));
}
if (v->m_dynamic) {
delete v;
v = NULL;
}
finalVars.push_back(std::move(var)); finalVars.push_back(std::move(var));
} }
} }
@ -772,8 +755,8 @@ bool Rule::evaluate(Transaction *trans,
finalVars = getFinalVars(trans); finalVars = getFinalVars(trans);
for (auto &v : finalVars) { for (auto &v : finalVars) {
const std::string value = *(v->m_value); const std::string value = v->m_value;
const std::string key = *(v->m_key); const std::string key = v->m_key;
std::list<std::pair<std::shared_ptr<std::string>, std::list<std::pair<std::shared_ptr<std::string>,
std::shared_ptr<std::string>>> values; std::shared_ptr<std::string>>> values;

View File

@ -790,9 +790,10 @@ int Transaction::processRequestBody() {
std::vector<const collection::Variable *> l; std::vector<const collection::Variable *> l;
m_variableRequestHeaders.resolve(&l); m_variableRequestHeaders.resolve(&l);
for (auto &a : l) { for (auto &a : l) {
std::string z(*a->m_key, 16, a->m_key->length() - 16); std::string z(a->m_key, 16, a->m_key.length() - 16);
z = z + ": " + *a->m_value; z = z + ": " + a->m_value;
fullRequest = fullRequest + z + "\n"; fullRequest = fullRequest + z + "\n";
delete a;
} }
fullRequest = fullRequest + "\n\n"; fullRequest = fullRequest + "\n\n";
@ -1423,10 +1424,11 @@ std::string Transaction::toOldAuditLogFormat(int parts,
audit_log << this->m_httpVersion << std::endl; audit_log << this->m_httpVersion << std::endl;
m_variableRequestHeaders.resolve(&l); m_variableRequestHeaders.resolve(&l);
for (auto h : l) { for (auto &h : l) {
size_t pos = strlen("REQUEST_HEADERS:"); size_t pos = strlen("REQUEST_HEADERS:");
audit_log << h->m_key->c_str() + pos << ": "; audit_log << h->m_key.c_str() + pos << ": ";
audit_log << h->m_value->c_str() << std::endl; audit_log << h->m_value.c_str() << std::endl;
delete h;
} }
audit_log << std::endl; audit_log << std::endl;
} }
@ -1459,10 +1461,11 @@ std::string Transaction::toOldAuditLogFormat(int parts,
audit_log << "--" << trailer << "-" << "F--" << std::endl; audit_log << "--" << trailer << "-" << "F--" << std::endl;
audit_log << "HTTP/" << m_httpVersion << " " << this->m_httpCodeReturned << std::endl; audit_log << "HTTP/" << m_httpVersion << " " << this->m_httpCodeReturned << std::endl;
m_variableResponseHeaders.resolve(&l); m_variableResponseHeaders.resolve(&l);
for (auto h : l) { for (auto &h : l) {
size_t pos = strlen("RESPONSE_HEADERS:"); size_t pos = strlen("RESPONSE_HEADERS:");
audit_log << h->m_key->c_str() + pos << ": "; audit_log << h->m_key.c_str() + pos << ": ";
audit_log << h->m_value->c_str() << std::endl; audit_log << h->m_value.c_str() << std::endl;
delete h;
} }
} }
audit_log << std::endl; audit_log << std::endl;
@ -1558,9 +1561,10 @@ std::string Transaction::toJSON(int parts) {
yajl_gen_map_open(g); yajl_gen_map_open(g);
m_variableRequestHeaders.resolve(&l); m_variableRequestHeaders.resolve(&l);
for (auto h : l) { for (auto &h : l) {
size_t pos = strlen("REQUEST_HEADERS:"); 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;
} }
/* end: request headers */ /* end: request headers */
@ -1588,9 +1592,10 @@ std::string Transaction::toJSON(int parts) {
yajl_gen_map_open(g); yajl_gen_map_open(g);
m_variableResponseHeaders.resolve(&l); m_variableResponseHeaders.resolve(&l);
for (auto h : l) { for (auto &h : l) {
size_t pos = strlen("RESPONSE_HEADERS:"); 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;
} }
/* end: response headers */ /* end: response headers */

View File

@ -42,14 +42,16 @@ void RemoteUser::evaluate(Transaction *transaction,
size_t pos; size_t pos;
std::string base64; std::string base64;
collection::Variable *var; collection::Variable *var;
std::string header;
transaction->m_variableRequestHeaders.resolve("authorization", l); std::vector<const collection::Variable *> *l2 = new std::vector<const collection::Variable *>();
transaction->m_variableRequestHeaders.resolve("authorization", l2);
if (l->size() < 1) { if (l2->size() < 1) {
return; goto clear;
} }
std::string header(*l->at(0)->m_value); header = std::string(l2->at(0)->m_value);
if (header.compare(0, 6, "Basic ") == 0) { if (header.compare(0, 6, "Basic ") == 0) {
base64 = std::string(header, 6, header.length()); base64 = std::string(header, 6, header.length());
@ -59,22 +61,27 @@ void RemoteUser::evaluate(Transaction *transaction,
pos = base64.find(":"); pos = base64.find(":");
if (pos == std::string::npos) { if (pos == std::string::npos) {
return; goto clear;
} }
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos)); transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
var = new collection::Variable(l->at(0)->m_key, var = new collection::Variable(&l2->at(0)->m_key,
std::make_shared<std::string>(transaction->m_variableRemoteUser)); &transaction->m_variableRemoteUser);
for (auto &i : l->at(0)->m_orign) { for (auto &i : l2->at(0)->m_orign) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin()); std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
origin->m_offset = i->m_offset; origin->m_offset = i->m_offset;
origin->m_length = i->m_length; origin->m_length = i->m_length;
var->m_orign.push_back(std::move(origin)); var->m_orign.push_back(std::move(origin));
} }
l->clear();
l->push_back(var); l->push_back(var);
clear:
for (auto &a : *l2) {
delete a;
}
l2->clear();
delete l2;
} }

View File

@ -126,24 +126,22 @@ class VariableModificatorCount : public Variable {
Rule *rule, Rule *rule,
std::vector<const collection::Variable *> *l) { std::vector<const collection::Variable *> *l) {
std::vector<const collection::Variable *> reslIn; std::vector<const collection::Variable *> reslIn;
std::string *res = NULL;
collection::Variable *val = NULL; collection::Variable *val = NULL;
int count = 0; int count = 0;
m_var->evaluate(transaction, rule, &reslIn); m_var->evaluate(transaction, rule, &reslIn);
for (const collection::Variable *a : reslIn) { for (const collection::Variable *a : reslIn) {
count++; count++;
if (a->m_dynamic) { delete a;
delete a; a = NULL;
a = NULL;
}
} }
reslIn.clear(); reslIn.clear();
res = new std::string(std::to_string(count)); std::string *res = new std::string(std::to_string(count));
std::string *name = new std::string(m_name);
val = new collection::Variable(&m_name, res); val = new collection::Variable(name, res);
val->m_dynamic = true; delete name;
delete res;
l->push_back(val); l->push_back(val);
return; return;

View File

@ -125,8 +125,10 @@ void XML::evaluate(Transaction *t,
content = reinterpret_cast<char *>( content = reinterpret_cast<char *>(
xmlNodeGetContent(nodes->nodeTab[i])); xmlNodeGetContent(nodes->nodeTab[i]));
if (content != NULL) { if (content != NULL) {
std::string *a = new std::string(content);
collection::Variable *var = new collection::Variable(&m_name, collection::Variable *var = new collection::Variable(&m_name,
new std::string(content)); a);
delete a;
l->push_back(var); l->push_back(var);
xmlFree(content); xmlFree(content);
} }

View File

@ -40,13 +40,12 @@ class XML_NoDictElement : public Variable {
: Variable("XML"), : Variable("XML"),
m_plain("[XML document tree]"), m_plain("[XML document tree]"),
m_var(&m_name, &m_plain) { m_var(&m_name, &m_plain) {
m_var.m_dynamic = false;
} }
void evaluate(Transaction *transaction, void evaluate(Transaction *transaction,
Rule *rule, Rule *rule,
std::vector<const collection::Variable *> *l) override { std::vector<const collection::Variable *> *l) override {
l->push_back(&m_var); l->push_back(new collection::Variable(&m_var));
} }
std::string m_plain; std::string m_plain;