Reduce the workload on VariableValue

Last compute at the last minute, if needed.
This commit is contained in:
Felipe Zimmerle
2020-09-17 19:51:34 -03:00
committed by Felipe Zimmerle
parent 8fa4fc67af
commit 820396f784
24 changed files with 255 additions and 172 deletions

View File

@@ -78,19 +78,15 @@ class AnchoredSetVariable : public std::unordered_multimap<std::string,
void unset();
void set(const std::string &key, const std::string &value,
size_t offset);
void set(const std::string &key, const bpstd::string_view &value,
size_t offset);
void set(const std::string &key, const char *value,
size_t offset);
void set(const std::string &key, const std::string &value, size_t offset) {
set(key, value, offset, value.size());
}
void set(const std::string &key, const std::string &value,
size_t offset, size_t len);
void setCopy(std::string key, std::string value, size_t offset);
void set(const std::string &key, const bpstd::string_view &value,
size_t offset);
void resolve(VariableValues *l);
void resolve(VariableValues *l,

View File

@@ -626,18 +626,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
int m_secRuleEngine;
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;
std::vector<std::shared_ptr<RequestBodyProcessor::MultipartPartTmpFile>> m_multipartPartTmpFiles;

View File

@@ -20,9 +20,13 @@
#include <memory>
#include <list>
#include <utility>
#include <vector>
#endif
#include "modsecurity/variable_origin.h"
#ifdef __cplusplus
#include "modsecurity/string_view.hpp"
#endif
#ifndef HEADERS_MODSECURITY_VARIABLE_VALUE_H_
#define HEADERS_MODSECURITY_VARIABLE_VALUE_H_
@@ -38,70 +42,208 @@ class VariableValue;
using VariableValues = std::vector<std::shared_ptr<const VariableValue>>;
using Origins = std::vector<VariableOrigin>;
class Collection;
class VariableValue {
public:
/**
*
*
* Use cases for VariableValue creation:
*
* AnchoredSet - Use case A (eg. ARGS). - Collection + Key
* Anchored - Use case B (eg. REQUEST_URI). - Key
* Custom - Use case C (eg. WEBAPP_ID). - Key
* CustomSet
* Fixed - Use case D (eg. TX). - Collection + Key
* Dynamic - Use case E (eg. ENV). - Collection + Key
*
*
* | Key | Collec. | Key + Collec. | Value | Full Name
* A | & | & | * | & | *
* B | x | & | * | & | &
* C | x | & | * | & | &
* D | & | & | * | & | *
* E | & | & | * | * | *
*
*
*
* Currently big picture of getName and getKey:
*
* getName()
* - Lua Engine - RuleWithOperator - Transaction
* - UpdateMatchedVar - logging (audit)
* - ExecuteOperatorAt
* - ResolveMatchMsg
* - RulesExceptions (key and value)
*
*
* getKey()
* - Transaction - Variable
* - LogGen - Contains
* - Regexp
*
*
* Performance strategy: Delay the name resolution till is really necessary.
*
*
*/
explicit VariableValue(const std::string *key,
/**
*
* Use case C + VariableModificatorCount
*
*
**/
explicit VariableValue(const std::string *collection,
const std::string *value = nullptr)
: m_collection(""),
m_key(*key),
m_keyWithCollection(*key),
m_value(value != nullptr?*value:"")
{ }
: m_origin(),
m_value(),
m_valueHolder(new std::string(value != nullptr?*value:"")), // FIXME: do we really need a copy here?
m_key(nullptr),
m_keyHolder(nullptr),
m_collection(collection)
{
m_value = m_valueHolder.get();
};
/* Use case D.1. - ARGS */
VariableValue(const std::string *collection,
std::unique_ptr<std::string> key,
std::unique_ptr<std::string> value)
: m_origin(),
m_value(nullptr),
m_valueHolder(std::move(value)),
m_key(nullptr),
m_keyHolder(std::move(key)),
m_collection(collection)
{
m_value = m_valueHolder.get();
m_key = m_keyHolder.get();
};
/* Use case D.2. - RULE */
VariableValue(const std::string *collection,
const std::string *key,
std::unique_ptr<std::string> value)
: m_origin(),
m_value(nullptr),
m_valueHolder(std::move(value)),
m_key(key),
m_keyHolder(nullptr),
m_collection(collection)
{
m_value = m_valueHolder.get();
};
/* Use case D.3. - TX */
VariableValue(const std::string *collection,
const std::string *key,
const std::string *value)
: m_collection(*collection),
m_key(*key),
m_keyWithCollection(*collection + ":" + *key),
m_value(*value)
{ }
: m_origin(),
m_value(value),
m_valueHolder(nullptr),
m_key(key),
m_keyHolder(nullptr),
m_collection(collection)
{ };
// FIXME: It maybe the case for VariableValue to use string_view for everything.
/* Use case D.4. - MATCHED_VARS */
VariableValue(const std::string *collection,
const std::string *key,
const bpstd::string_view *value)
: m_origin(),
m_value(),
m_valueHolder(std::unique_ptr<std::string>(new std::string(value->c_str()))),
m_key(key),
m_keyHolder(nullptr),
m_collection(collection)
{
m_value = m_valueHolder.get();
};
/* Use case E.1. - Env */
VariableValue(std::unique_ptr<std::string> value,
std::unique_ptr<std::string> key,
std::shared_ptr<std::string> collection)
: m_origin(),
m_value(nullptr),
m_valueHolder(std::move(value)),
m_key(nullptr),
m_keyHolder(std::move(key)),
m_collection(collection.get())
{
m_value = m_valueHolder.get();
m_key = m_keyHolder.get();
};
/* Use case E.2. - DURATION */
VariableValue(std::unique_ptr<std::string> value,
const std::string *collection)
: m_origin(),
m_value(nullptr),
m_valueHolder(std::move(value)),
m_key(nullptr),
m_keyHolder(nullptr),
m_collection(collection)
{
m_value = m_valueHolder.get();
};
VariableValue(const VariableValue &o) = delete;
const std::string& getName() const noexcept {
return m_keyWithCollection;
}
VariableValue operator=(const VariableValue &o) = delete;
const std::string& getValue() const noexcept {
return m_value;
return *m_value;
}
const std::string& getKey() const {
return m_key;
const std::string& getKey() const noexcept {
return *m_key;
}
const std::string& getCollection() const {
return m_collection;
inline const std::string getName() const noexcept {
if (m_key == nullptr || m_key->empty()) {
return *m_collection;
}
return *m_collection + ":" + *m_key;
}
void setValue(const std::string &value) {
m_value = value;
m_value = &value;
}
void addOrigin(VariableOrigin origin) {
m_orign.push_back(std::move(origin));
m_origin.push_back(std::move(origin));
}
const Origins& getOrigin() const {
return m_orign;
return m_origin;
}
private:
Origins m_orign;
std::string m_collection;
std::string m_key;
std::string m_keyWithCollection;
std::string m_value;
Origins m_origin;
const std::string *m_value;
std::unique_ptr<std::string> m_valueHolder;
const std::string *m_key;
std::unique_ptr<std::string> m_keyHolder;
const std::string *m_collection;
};
} // namespace modsecurity