mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 13:56:01 +03:00
Having RunTimeString in a better shape
This is an effort towards better understanding the issues reported on #2376
This commit is contained in:
parent
d3ba2318d6
commit
bff82cd80d
@ -122,7 +122,7 @@ bool Operator::evaluate(Transaction *transaction,
|
||||
Operator *Operator::instantiate(std::string op, std::string param_str) {
|
||||
std::string op_ = utils::string::tolower(op);
|
||||
std::unique_ptr<RunTimeString> param(new RunTimeString());
|
||||
param->appendText(param_str);
|
||||
param->append(param_str);
|
||||
|
||||
IF_MATCH(beginswith) { return new BeginsWith(std::move(param)); }
|
||||
IF_MATCH(contains) { return new Contains(std::move(param)); }
|
||||
|
@ -5621,7 +5621,7 @@ namespace yy {
|
||||
case 438: // run_time_string: run_time_string "FREE_TEXT_QUOTE_MACRO_EXPANSION"
|
||||
#line 3036 "seclang-parser.yy"
|
||||
{
|
||||
yystack_[1].value.as < std::unique_ptr<RunTimeString> > ()->appendText(yystack_[0].value.as < std::string > ());
|
||||
yystack_[1].value.as < std::unique_ptr<RunTimeString> > ()->append(yystack_[0].value.as < std::string > ());
|
||||
yylhs.value.as < std::unique_ptr<RunTimeString> > () = std::move(yystack_[1].value.as < std::unique_ptr<RunTimeString> > ());
|
||||
}
|
||||
#line 5628 "seclang-parser.cc"
|
||||
@ -5630,7 +5630,7 @@ namespace yy {
|
||||
case 439: // run_time_string: run_time_string var
|
||||
#line 3041 "seclang-parser.yy"
|
||||
{
|
||||
yystack_[1].value.as < std::unique_ptr<RunTimeString> > ()->appendVar(std::move(yystack_[0].value.as < std::unique_ptr<Variable> > ()));
|
||||
yystack_[1].value.as < std::unique_ptr<RunTimeString> > ()->append(std::move(yystack_[0].value.as < std::unique_ptr<Variable> > ()));
|
||||
yylhs.value.as < std::unique_ptr<RunTimeString> > () = std::move(yystack_[1].value.as < std::unique_ptr<RunTimeString> > ());
|
||||
}
|
||||
#line 5637 "seclang-parser.cc"
|
||||
@ -5640,7 +5640,7 @@ namespace yy {
|
||||
#line 3046 "seclang-parser.yy"
|
||||
{
|
||||
std::unique_ptr<RunTimeString> r(new RunTimeString());
|
||||
r->appendText(yystack_[0].value.as < std::string > ());
|
||||
r->append(yystack_[0].value.as < std::string > ());
|
||||
yylhs.value.as < std::unique_ptr<RunTimeString> > () = std::move(r);
|
||||
}
|
||||
#line 5647 "seclang-parser.cc"
|
||||
@ -5650,7 +5650,7 @@ namespace yy {
|
||||
#line 3052 "seclang-parser.yy"
|
||||
{
|
||||
std::unique_ptr<RunTimeString> r(new RunTimeString());
|
||||
r->appendVar(std::move(yystack_[0].value.as < std::unique_ptr<Variable> > ()));
|
||||
r->append(std::move(yystack_[0].value.as < std::unique_ptr<Variable> > ()));
|
||||
yylhs.value.as < std::unique_ptr<RunTimeString> > () = std::move(r);
|
||||
}
|
||||
#line 5657 "seclang-parser.cc"
|
||||
|
@ -3034,24 +3034,24 @@ setvar_action:
|
||||
run_time_string:
|
||||
run_time_string FREE_TEXT_QUOTE_MACRO_EXPANSION
|
||||
{
|
||||
$1->appendText($2);
|
||||
$1->append($2);
|
||||
$$ = std::move($1);
|
||||
}
|
||||
| run_time_string var
|
||||
{
|
||||
$1->appendVar(std::move($2));
|
||||
$1->append(std::move($2));
|
||||
$$ = std::move($1);
|
||||
}
|
||||
| FREE_TEXT_QUOTE_MACRO_EXPANSION
|
||||
{
|
||||
std::unique_ptr<RunTimeString> r(new RunTimeString());
|
||||
r->appendText($1);
|
||||
r->append($1);
|
||||
$$ = std::move(r);
|
||||
}
|
||||
| var
|
||||
{
|
||||
std::unique_ptr<RunTimeString> r(new RunTimeString());
|
||||
r->appendVar(std::move($1));
|
||||
r->append(std::move($1));
|
||||
$$ = std::move(r);
|
||||
}
|
||||
;
|
||||
|
@ -31,38 +31,22 @@
|
||||
namespace modsecurity {
|
||||
|
||||
|
||||
void RunTimeString::appendText(const std::string &text) {
|
||||
std::unique_ptr<RunTimeElementHolder> r(new RunTimeElementHolder);
|
||||
r->m_string = text;
|
||||
m_elements.push_back(std::move(r));
|
||||
void RunTimeString::append(const std::string &text) {
|
||||
m_elements.emplace_back(new ElementHolder(text));
|
||||
}
|
||||
|
||||
|
||||
void RunTimeString::appendVar(
|
||||
std::unique_ptr<modsecurity::variables::Variable> var) {
|
||||
std::unique_ptr<RunTimeElementHolder> r(new RunTimeElementHolder);
|
||||
r->m_variable = std::move(var);
|
||||
m_elements.push_back(std::move(r));
|
||||
void RunTimeString::append(std::unique_ptr<Variable> var) {
|
||||
m_elements.emplace_back(new ElementHolder(std::move(var)));
|
||||
m_containsMacro = true;
|
||||
}
|
||||
|
||||
|
||||
std::string RunTimeString::evaluate(Transaction *transaction) {
|
||||
std::string RunTimeString::evaluate(/* const */ Transaction *transaction) const noexcept {
|
||||
std::string retString;
|
||||
// FIXME: Educated guess the size of retString based on the size of the elements.
|
||||
for (auto &element : m_elements) {
|
||||
if (element->m_string.size() > 0) {
|
||||
retString.append(element->m_string);
|
||||
} else if (element->m_variable != nullptr && transaction != nullptr) {
|
||||
std::vector<const VariableValue *> l;
|
||||
element->m_variable->evaluate(transaction, &l);
|
||||
if (!l.empty()) {
|
||||
retString.append(l[0]->getValue());
|
||||
}
|
||||
for (auto &i : l) {
|
||||
delete i;
|
||||
}
|
||||
}
|
||||
element->appendValueTo(transaction, retString);
|
||||
}
|
||||
return retString;
|
||||
}
|
||||
|
@ -33,33 +33,11 @@
|
||||
|
||||
namespace modsecurity {
|
||||
|
||||
class RunTimeElementHolder {
|
||||
public:
|
||||
RunTimeElementHolder()
|
||||
: m_string(""),
|
||||
m_variable(nullptr)
|
||||
{ };
|
||||
|
||||
|
||||
RunTimeElementHolder(const RunTimeElementHolder &other)
|
||||
: m_string(other.m_string),
|
||||
m_variable(other.m_variable) {
|
||||
variables::RuleVariable *rv = dynamic_cast<variables::RuleVariable *>(m_variable.get());
|
||||
if (rv != nullptr) {
|
||||
auto nrv = rv->clone();
|
||||
rv = dynamic_cast<variables::RuleVariable *>(nrv);
|
||||
rv->populate(nullptr);
|
||||
m_variable = std::unique_ptr<variables::Variable>(nrv);
|
||||
}
|
||||
};
|
||||
|
||||
/* protected: */
|
||||
std::string m_string;
|
||||
std::shared_ptr<variables::Variable> m_variable;
|
||||
};
|
||||
|
||||
class RunTimeString {
|
||||
public:
|
||||
using Variable = variables::Variable;
|
||||
using RuleVariable = variables::RuleVariable;
|
||||
|
||||
RunTimeString()
|
||||
: m_containsMacro(false),
|
||||
m_elements()
|
||||
@ -71,37 +49,124 @@ class RunTimeString {
|
||||
m_elements()
|
||||
{
|
||||
for (auto &m : other.m_elements) {
|
||||
m_elements.push_back(std::unique_ptr<RunTimeElementHolder>(new RunTimeElementHolder(*m.get())));
|
||||
m_elements.emplace_back(new ElementHolder(*m.get()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void appendText(const std::string &text);
|
||||
void appendVar(std::unique_ptr<modsecurity::variables::Variable> var);
|
||||
|
||||
|
||||
std::string evaluate(Transaction *t);
|
||||
|
||||
inline std::string evaluate() {
|
||||
return evaluate(NULL);
|
||||
RunTimeString& operator=(RunTimeString other)
|
||||
{
|
||||
m_containsMacro = other.m_containsMacro;
|
||||
for (auto &m : other.m_elements) {
|
||||
m_elements.emplace_back(new ElementHolder(*m.get()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline bool containsMacro() const { return m_containsMacro; }
|
||||
void append(const std::string &text);
|
||||
void append(std::unique_ptr<Variable> var);
|
||||
|
||||
|
||||
void populate(RuleWithActions *rule) {
|
||||
/*
|
||||
*
|
||||
* FIXME: Transaction should be const here. Variables resolution does
|
||||
* not change anything on transaction instance.
|
||||
*
|
||||
*/
|
||||
std::string evaluate(/* const */ Transaction *t = nullptr) const noexcept;
|
||||
|
||||
|
||||
inline bool containsMacro() const noexcept {
|
||||
return m_containsMacro;
|
||||
}
|
||||
|
||||
|
||||
void populate(RuleWithActions *rule) noexcept {
|
||||
for (auto &a : m_elements) {
|
||||
modsecurity::variables::RuleVariable *vrule = dynamic_cast<variables::RuleVariable *>(a->m_variable.get());
|
||||
a->populate(rule);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ElementHolder {
|
||||
public:
|
||||
ElementHolder()
|
||||
: m_string(""),
|
||||
m_variable(nullptr)
|
||||
{ };
|
||||
|
||||
explicit ElementHolder(std::unique_ptr<Variable> variable)
|
||||
: m_string(""),
|
||||
m_variable(std::move(variable))
|
||||
{ };
|
||||
|
||||
explicit ElementHolder(const std::string &str)
|
||||
: m_string(str),
|
||||
m_variable(nullptr)
|
||||
{ };
|
||||
|
||||
ElementHolder(const ElementHolder &other)
|
||||
: m_string(other.m_string),
|
||||
m_variable(nullptr) {
|
||||
RuleVariable *rv = dynamic_cast<RuleVariable *>(other.m_variable.get());
|
||||
if (rv != nullptr) {
|
||||
auto nrv = rv->clone();
|
||||
rv = dynamic_cast<RuleVariable *>(nrv);
|
||||
rv->populate(nullptr);
|
||||
m_variable = std::unique_ptr<Variable>(nrv);
|
||||
/* m_variable = nullptr; */
|
||||
} else {
|
||||
m_variable = other.m_variable;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
void appendValueTo(/* const */ Transaction *transaction, std::string &v) const noexcept {
|
||||
if (m_variable && transaction) {
|
||||
std::vector<const VariableValue *> l;
|
||||
m_variable->evaluate(transaction, &l);
|
||||
if (!l.empty()) {
|
||||
v.append(l[0]->getValue());
|
||||
}
|
||||
for (auto &i : l) {
|
||||
delete i;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
v.append(m_string);
|
||||
}
|
||||
|
||||
|
||||
void populate(RuleWithActions *rule) noexcept {
|
||||
if (!m_variable) {
|
||||
return;
|
||||
}
|
||||
|
||||
RuleVariable *vrule = dynamic_cast<RuleVariable *>(m_variable.get());
|
||||
if (vrule != nullptr) {
|
||||
vrule->populate(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_string;
|
||||
/*
|
||||
*
|
||||
* FIXME: In the current state m_variable should be a unique_ptr. There
|
||||
* is no copy for variables, thus having a shared pointer here.
|
||||
* As an optimization we can have it as a shared_ptr to reduce the
|
||||
* memory footprint in anchored variables.
|
||||
*
|
||||
*/
|
||||
std::shared_ptr<Variable> m_variable;
|
||||
};
|
||||
|
||||
private:
|
||||
bool m_containsMacro;
|
||||
std::list<std::unique_ptr<RunTimeElementHolder>> m_elements;
|
||||
bool m_containsMacro:1;
|
||||
std::vector<std::unique_ptr<ElementHolder>> m_elements;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user