diff --git a/headers/modsecurity/anchored_set_variable.h b/headers/modsecurity/anchored_set_variable.h index a92884b8f..af27cc6eb 100644 --- a/headers/modsecurity/anchored_set_variable.h +++ b/headers/modsecurity/anchored_set_variable.h @@ -47,7 +47,10 @@ class KeyExclusions; struct MyEqual { - bool operator()(const std::string& Left, const std::string& Right) const { + using is_transparent = void; + + template + bool operator()(const T& Left, const U& Right) const { return Left.size() == Right.size() && std::equal(Left.begin(), Left.end(), Right.begin(), [](char a, char b) { @@ -57,7 +60,10 @@ struct MyEqual { }; struct MyHash{ - size_t operator()(const std::string& Keyval) const { + using is_transparent = void; + + template + size_t operator()(const T& Keyval) const { // You might need a better hash function than this size_t h = 0; std::for_each(Keyval.begin(), Keyval.end(), [&](char c) { @@ -88,7 +94,7 @@ class AnchoredSetVariable : public std::unordered_multimap &l, variables::KeyExclusions &ke); - void resolve(const std::string &key, + void resolve(std::string_view key, std::vector &l); void resolveRegularExpression(Utils::Regex *r, @@ -98,7 +104,7 @@ class AnchoredSetVariable : public std::unordered_multimap &l, variables::KeyExclusions &ke); - std::unique_ptr resolveFirst(const std::string &key); + std::unique_ptr resolveFirst(std::string_view key); Transaction *m_transaction; std::string m_name; diff --git a/headers/modsecurity/anchored_set_variable_translation_proxy.h b/headers/modsecurity/anchored_set_variable_translation_proxy.h index b1cda117e..581ca02b4 100644 --- a/headers/modsecurity/anchored_set_variable_translation_proxy.h +++ b/headers/modsecurity/anchored_set_variable_translation_proxy.h @@ -56,7 +56,7 @@ class AnchoredSetVariableTranslationProxy { translate(l); } - void resolve(const std::string &key, + void resolve(std::string_view key, std::vector &l) { m_fount->resolve(key, l); translate(l); @@ -75,7 +75,7 @@ class AnchoredSetVariableTranslationProxy { translate(l); }; - std::unique_ptr resolveFirst(const std::string &key) { + std::unique_ptr resolveFirst(std::string_view key) { std::vector l; resolve(l); diff --git a/headers/modsecurity/collection/collection.h b/headers/modsecurity/collection/collection.h index d8e0cc0c9..fa122210d 100644 --- a/headers/modsecurity/collection/collection.h +++ b/headers/modsecurity/collection/collection.h @@ -45,25 +45,25 @@ class Collection { explicit Collection(std::string_view a) : m_name(a) { } virtual ~Collection() { } - virtual bool storeOrUpdateFirst(const std::string& key, + virtual bool storeOrUpdateFirst(std::string_view key, std::string_view value) = 0; - virtual bool updateFirst(const std::string& key, + virtual bool updateFirst(std::string_view key, std::string_view value) = 0; - virtual void del(const std::string& key) = 0; + virtual void del(std::string_view key) = 0; - virtual void setExpiry(const std::string& key, int32_t expiry_seconds) = 0; + virtual void setExpiry(std::string_view key, int32_t expiry_seconds) = 0; virtual std::unique_ptr resolveFirst( - const std::string& var) = 0; + std::string_view var) = 0; - virtual void resolveSingleMatch(const std::string& var, + virtual void resolveSingleMatch(std::string_view var, std::vector &l) = 0; - virtual void resolveMultiMatches(const std::string& var, + virtual void resolveMultiMatches(std::string_view var, std::vector &l, variables::KeyExclusions &ke) = 0; - virtual void resolveRegularExpression(const std::string& var, + virtual void resolveRegularExpression(std::string_view var, std::vector &l, variables::KeyExclusions &ke) = 0; diff --git a/src/anchored_set_variable.cc b/src/anchored_set_variable.cc index ea1ec9e0c..f918dfb77 100644 --- a/src/anchored_set_variable.cc +++ b/src/anchored_set_variable.cc @@ -89,8 +89,9 @@ void AnchoredSetVariable::resolve( } -void AnchoredSetVariable::resolve(const std::string &key, +void AnchoredSetVariable::resolve(std::string_view key, std::vector &l) { + auto range = this->equal_range(key); for (auto it = range.first; it != range.second; ++it) { l.push_back(new VariableValue(*it->second)); @@ -99,7 +100,7 @@ void AnchoredSetVariable::resolve(const std::string &key, std::unique_ptr AnchoredSetVariable::resolveFirst( - const std::string &key) { + std::string_view key) { if (auto search = this->find(key); search != this->end()) { return std::make_unique(search->second->getValue()); diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index 97272f1c6..d5474d7fe 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -30,9 +30,7 @@ #include "src/utils/string.h" -namespace modsecurity { -namespace collection { -namespace backend { +namespace modsecurity::collection::backend { InMemoryPerProcess::InMemoryPerProcess(std::string_view name) : @@ -46,7 +44,7 @@ InMemoryPerProcess::~InMemoryPerProcess() { template -inline void __store(Map &map, const std::string& key, std::string_view value) { +inline void __store(Map &map, std::string_view key, std::string_view value) { // NOTE: should be called with write-lock previously acquired map.emplace(key, value); @@ -55,7 +53,7 @@ inline void __store(Map &map, const std::string& key, std::string_view value) { template inline bool __updateFirst(Map &map, - const std::string& key, + std::string_view key, std::string_view value) { // NOTE: should be called with write-lock previously acquired @@ -68,13 +66,13 @@ inline bool __updateFirst(Map &map, } -void InMemoryPerProcess::store(const std::string& key, std::string_view value) { +void InMemoryPerProcess::store(std::string_view key, std::string_view value) { const std::lock_guard lock(m_mutex); // write lock (exclusive access) __store(m_map, key, value); } -bool InMemoryPerProcess::storeOrUpdateFirst(const std::string& key, +bool InMemoryPerProcess::storeOrUpdateFirst(std::string_view key, std::string_view value) { const std::lock_guard lock(m_mutex); // write lock (exclusive access) if (__updateFirst(m_map, key, value) == false) { @@ -84,29 +82,31 @@ bool InMemoryPerProcess::storeOrUpdateFirst(const std::string& key, } -bool InMemoryPerProcess::updateFirst(const std::string& key, +bool InMemoryPerProcess::updateFirst(std::string_view key, std::string_view value) { const std::lock_guard lock(m_mutex); // write lock (exclusive access) return __updateFirst(m_map, key, value); } -void InMemoryPerProcess::del(const std::string& key) { +void InMemoryPerProcess::del(std::string_view key) { const std::lock_guard lock(m_mutex); // write lock (exclusive access) - m_map.erase(key); + const auto range = m_map.equal_range(key); + m_map.erase(range.first, range.second); } -void InMemoryPerProcess::delIfExpired(const std::string& key) { +void InMemoryPerProcess::delIfExpired(std::string_view key) { const std::lock_guard lock(m_mutex); // write lock (exclusive access) + const auto range = m_map.equal_range(key); // Double check the status while within the mutex - const auto iter = std::find_if(m_map.begin(), m_map.end(), - [&key](const auto &x) { return x.first == key && x.second.isExpired(); }); - if (iter != m_map.end()) { - m_map.erase(key); + const auto iter = std::find_if(range.first, range.second, + [](const auto &x) { return x.second.isExpired(); }); + if (iter != range.second) { + m_map.erase(range.first, range.second); } } -void InMemoryPerProcess::setExpiry(const std::string& key, int32_t expiry_seconds) { +void InMemoryPerProcess::setExpiry(std::string_view key, int32_t expiry_seconds) { const std::lock_guard lock(m_mutex); // write lock (exclusive access) if (const auto search = m_map.find(key); search != m_map.end()) { @@ -120,7 +120,7 @@ void InMemoryPerProcess::setExpiry(const std::string& key, int32_t expiry_second } -void InMemoryPerProcess::resolveSingleMatch(const std::string& var, +void InMemoryPerProcess::resolveSingleMatch(std::string_view var, std::vector &l) { std::list expiredVars; @@ -145,7 +145,7 @@ void InMemoryPerProcess::resolveSingleMatch(const std::string& var, } -void InMemoryPerProcess::resolveMultiMatches(const std::string& var, +void InMemoryPerProcess::resolveMultiMatches(std::string_view var, std::vector &l, variables::KeyExclusions &ke) { const auto keySize = var.size(); l.reserve(15); @@ -192,7 +192,7 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var, } -void InMemoryPerProcess::resolveRegularExpression(const std::string& var, +void InMemoryPerProcess::resolveRegularExpression(std::string_view var, std::vector &l, variables::KeyExclusions &ke) { Utils::Regex r(var, true); std::list expiredVars; @@ -225,7 +225,7 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var, std::unique_ptr InMemoryPerProcess::resolveFirst( - const std::string& var) { + std::string_view var) { std::unique_ptr ret; std::list expiredVars; @@ -252,6 +252,4 @@ std::unique_ptr InMemoryPerProcess::resolveFirst( } -} // namespace backend -} // namespace collection -} // namespace modsecurity +} // namespace modsecurity::collection::backend diff --git a/src/collection/backend/in_memory-per_process.h b/src/collection/backend/in_memory-per_process.h index b6f8c1439..8cd70caf2 100644 --- a/src/collection/backend/in_memory-per_process.h +++ b/src/collection/backend/in_memory-per_process.h @@ -14,7 +14,9 @@ */ -#ifdef __cplusplus +#ifndef SRC_COLLECTION_BACKEND_IN_MEMORY_PER_PROCESS_H_ +#define SRC_COLLECTION_BACKEND_IN_MEMORY_PER_PROCESS_H_ + #include #include #include @@ -24,21 +26,13 @@ #include #include #include -#endif - #include "modsecurity/variable_value.h" #include "modsecurity/collection/collection.h" #include "src/collection/backend/collection_data.h" #include "src/variables/variable.h" -#ifndef SRC_COLLECTION_BACKEND_IN_MEMORY_PER_PROCESS_H_ -#define SRC_COLLECTION_BACKEND_IN_MEMORY_PER_PROCESS_H_ - -#ifdef __cplusplus -namespace modsecurity { -namespace collection { -namespace backend { +namespace modsecurity::collection::backend { /* * FIXME: @@ -50,7 +44,10 @@ namespace backend { * */ struct MyEqual { - bool operator()(const std::string& Left, const std::string& Right) const { + using is_transparent = void; + + template + bool operator()(const T& Left, const U& Right) const { return Left.size() == Right.size() && std::equal(Left.begin(), Left.end(), Right.begin(), [](char a, char b) { @@ -60,7 +57,10 @@ struct MyEqual { }; struct MyHash{ - size_t operator()(const std::string& Keyval) const { + using is_transparent = void; + + template + size_t operator()(const T& Keyval) const { // You might need a better hash function than this size_t h = 0; std::for_each(Keyval.begin(), Keyval.end(), [&](char c) { @@ -75,28 +75,28 @@ class InMemoryPerProcess : public: explicit InMemoryPerProcess(std::string_view name); ~InMemoryPerProcess() override; - void store(const std::string& key, std::string_view value); + void store(std::string_view key, std::string_view value); - bool storeOrUpdateFirst(const std::string& key, + bool storeOrUpdateFirst(std::string_view key, std::string_view value) override; - bool updateFirst(const std::string& key, + bool updateFirst(std::string_view key, std::string_view value) override; - void del(const std::string& key) override; + void del(std::string_view key) override; - void delIfExpired(const std::string& key); + void delIfExpired(std::string_view key); - void setExpiry(const std::string& key, int32_t expiry_seconds) override; + void setExpiry(std::string_view key, int32_t expiry_seconds) override; - std::unique_ptr resolveFirst(const std::string& var) override; + std::unique_ptr resolveFirst(std::string_view var) override; - void resolveSingleMatch(const std::string& var, + void resolveSingleMatch(std::string_view var, std::vector &l) override; - void resolveMultiMatches(const std::string& var, + void resolveMultiMatches(std::string_view var, std::vector &l, variables::KeyExclusions &ke) override; - void resolveRegularExpression(const std::string& var, + void resolveRegularExpression(std::string_view var, std::vector &l, variables::KeyExclusions &ke) override; @@ -117,10 +117,7 @@ class InMemoryPerProcess : std::shared_mutex m_mutex; }; -} // namespace backend -} // namespace collection -} // namespace modsecurity -#endif +} // namespace modsecurity::collection::backend #endif // SRC_COLLECTION_BACKEND_IN_MEMORY_PER_PROCESS_H_ diff --git a/src/collection/backend/lmdb.cc b/src/collection/backend/lmdb.cc index 64a6534c7..454a802c4 100644 --- a/src/collection/backend/lmdb.cc +++ b/src/collection/backend/lmdb.cc @@ -33,9 +33,7 @@ #undef LMDB_STDOUT_COUT -namespace modsecurity { -namespace collection { -namespace backend { +namespace modsecurity::collection::backend { #ifdef WITH_LMDB @@ -154,7 +152,7 @@ void LMDB::lmdb_debug(int rc, const std::string &op, const std::string &scope) { } -std::unique_ptr LMDB::resolveFirst(const std::string& var) { +std::unique_ptr LMDB::resolveFirst(std::string_view var) { int rc; MDB_val mdb_key; MDB_val mdb_value; @@ -192,7 +190,7 @@ std::unique_ptr LMDB::resolveFirst(const std::string& var) { } -void LMDB::setExpiry(const std::string &key, int32_t expiry_seconds) { +void LMDB::setExpiry(std::string_view key, int32_t expiry_seconds) { int rc; MDB_txn *txn; MDB_val mdb_key; @@ -250,7 +248,7 @@ void LMDB::setExpiry(const std::string &key, int32_t expiry_seconds) { return; } -void LMDB::delIfExpired(const std::string& key) { +void LMDB::delIfExpired(std::string_view key) { MDB_txn *txn; MDB_val mdb_key; MDB_val mdb_value_ret; @@ -295,7 +293,7 @@ void LMDB::delIfExpired(const std::string& key) { return; } -bool LMDB::storeOrUpdateFirst(const std::string &key, +bool LMDB::storeOrUpdateFirst(std::string_view key, std::string_view value) { int rc; MDB_txn *txn; @@ -355,7 +353,7 @@ bool LMDB::storeOrUpdateFirst(const std::string &key, } -void LMDB::resolveSingleMatch(const std::string& var, +void LMDB::resolveSingleMatch(std::string_view var, std::vector &l) { int rc; MDB_txn *txn; @@ -399,7 +397,7 @@ void LMDB::resolveSingleMatch(const std::string& var, } -bool LMDB::updateFirst(const std::string &key, +bool LMDB::updateFirst(std::string_view key, std::string_view value) { int rc; MDB_txn *txn; @@ -463,7 +461,7 @@ bool LMDB::updateFirst(const std::string &key, } -void LMDB::del(const std::string& key) { +void LMDB::del(std::string_view key) { int rc; MDB_txn *txn; MDB_val mdb_key; @@ -507,7 +505,7 @@ void LMDB::del(const std::string& key) { return; } -void LMDB::resolveMultiMatches(const std::string& var, +void LMDB::resolveMultiMatches(std::string_view var, std::vector &l, variables::KeyExclusions &ke) { MDB_val key, data; @@ -578,7 +576,7 @@ void LMDB::resolveMultiMatches(const std::string& var, } -void LMDB::resolveRegularExpression(const std::string& var, +void LMDB::resolveRegularExpression(std::string_view var, std::vector &l, variables::KeyExclusions &ke) { MDB_val key, data; @@ -672,6 +670,4 @@ MDBEnvProvider::~MDBEnvProvider() { #endif -} // namespace backend -} // namespace collection -} // namespace modsecurity +} // namespace modsecurity::collection::backend diff --git a/src/collection/backend/lmdb.h b/src/collection/backend/lmdb.h index 54630e954..60bcceb5a 100644 --- a/src/collection/backend/lmdb.h +++ b/src/collection/backend/lmdb.h @@ -14,7 +14,9 @@ */ -#ifdef __cplusplus +#ifndef SRC_COLLECTION_BACKEND_LMDB_H_ +#define SRC_COLLECTION_BACKEND_LMDB_H_ + #include #include #include @@ -23,7 +25,6 @@ #include #include #include -#endif #ifdef WITH_LMDB #include @@ -36,15 +37,9 @@ #include "modsecurity/collection/collection.h" #include "src/variables/variable.h" -#ifndef SRC_COLLECTION_BACKEND_LMDB_H_ -#define SRC_COLLECTION_BACKEND_LMDB_H_ - #ifdef WITH_LMDB -#ifdef __cplusplus -namespace modsecurity { -namespace collection { -namespace backend { +namespace modsecurity::collection::backend { /** @@ -97,24 +92,24 @@ class LMDB : public: explicit LMDB(const std::string &name); - bool storeOrUpdateFirst(const std::string &key, + bool storeOrUpdateFirst(std::string_view key, std::string_view value) override; - bool updateFirst(const std::string &key, + bool updateFirst(std::string_view key, std::string_view value) override; - void del(const std::string& key) override; + void del(std::string_view key) override; - void setExpiry(const std::string& key, int32_t expiry_seconds) override; + void setExpiry(std::string_view key, int32_t expiry_seconds) override; - std::unique_ptr resolveFirst(const std::string& var) override; + std::unique_ptr resolveFirst(std::string_view var) override; - void resolveSingleMatch(const std::string& var, + void resolveSingleMatch(std::string_view var, std::vector &l) override; - void resolveMultiMatches(const std::string& var, + void resolveMultiMatches(std::string_view var, std::vector &l, variables::KeyExclusions &ke) override; - void resolveRegularExpression(const std::string& var, + void resolveRegularExpression(std::string_view var, std::vector &l, variables::KeyExclusions &ke) override; @@ -130,10 +125,7 @@ class LMDB : bool isOpen; }; -} // namespace backend -} // namespace collection -} // namespace modsecurity -#endif +} // namespace modsecurity::collection::backend #endif // WITH_LMDB diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index b08260279..1e2d923fb 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -37,6 +37,7 @@ #include "modsecurity/collection/collections.h" #include "src/utils/string.h" +using namespace std::literals; namespace modsecurity { namespace RequestBodyProcessor { @@ -740,17 +741,18 @@ int Multipart::process_part_header(std::string *error, int offset) { m_mpp->m_last_header_line.assign(""); } - if (m_mpp->m_headers.count("Content-Disposition") == 0) { + const auto it = m_mpp->m_headers.find("Content-Disposition"sv); + if (it == m_mpp->m_headers.end()) { const auto err = "Multipart: Part missing Content-Disposition header."; ms_dbg_a(m_transaction, 1, err); error->assign(err); return false; } - header_value = m_mpp->m_headers.at("Content-Disposition").second; + header_value = it->second.second; try { rc = parse_content_disposition(header_value.c_str(), - m_mpp->m_headers.at("Content-Disposition").first); + it->second.first); } catch (...) { ms_dbg_a(m_transaction, 1, "Multipart: Unexpected error parsing Content-Disposition header."); @@ -835,10 +837,11 @@ int Multipart::process_part_header(std::string *error, int offset) { utils::string::chomp(new_value); /* update the header value in the table */ - header_value = m_mpp->m_headers.at( - m_mpp->m_last_header_name).second; - new_value = header_value + " " + new_value; - m_mpp->m_headers.at(m_mpp->m_last_header_name).second = new_value; + const auto it = m_mpp->m_headers.find(m_mpp->m_last_header_name); + assert(it != m_mpp->m_headers.end()); + header_value = it->second.second; + new_value = fmt::format("{} {}", header_value, new_value); + it->second.second = new_value; ms_dbg_a(m_transaction, 9, fmt::format("Multipart: " \ "Continued folder header \"{}\" with \"{}\"", @@ -921,10 +924,9 @@ int Multipart::process_part_header(std::string *error, int offset) { m_mpp->m_last_header_name.assign(header_name); - m_mpp->m_headers.emplace( - std::string(header_name), std::make_pair(offset - len + i, - std::string(header_value))); + header_name, std::make_pair(offset - len + i, + header_value)); ms_dbg_a(m_transaction, 9, fmt::format("Multipart: " \ "Added part header \"{}\" \"{}\".", diff --git a/src/request_body_processor/multipart.h b/src/request_body_processor/multipart.h index bfada4b97..2ba26f5dd 100644 --- a/src/request_body_processor/multipart.h +++ b/src/request_body_processor/multipart.h @@ -13,14 +13,15 @@ * */ +#ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ +#define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ + #include #include #include #include #include - -#ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ -#define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ +#include #include "modsecurity/transaction.h" @@ -33,7 +34,10 @@ namespace RequestBodyProcessor { struct MyHash { - size_t operator()(const std::string& Keyval) const { + using is_transparent = void; + + template + size_t operator()(const T& Keyval) const { size_t h = 0; std::for_each(Keyval.begin(), Keyval.end(), [&](char c) { h += tolower(c); @@ -44,7 +48,10 @@ struct MyHash { struct MyEqual { - bool operator()(const std::string& Left, const std::string& Right) const { + using is_transparent = void; + + template + bool operator()(const T& Left, const U& Right) const { return Left.size() == Right.size() && std::equal(Left.begin(), Left.end(), Right.begin(), [](char a, char b) { diff --git a/src/variables/variable.h b/src/variables/variable.h index 2b22e85ea..4e9cb90c5 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -183,9 +183,7 @@ class VariableMonkeyResolution { collection_delimiter_offset = variable.find(":"); } std::string_view col; // collection name excluding individual variable specification - // NOTE: cannot use std::string_view here because resolve - // needs to receive a std::string to call find - std::string var; // variable within the collection + std::string_view var; // variable within the collection if (collection_delimiter_offset == std::string::npos) { col = variable; } else { @@ -509,9 +507,7 @@ class VariableMonkeyResolution { } } else { const auto col = variable.substr(0, collection); - // NOTE: cannot use std::string_view here because resolveFirst - // needs to receive a std::string to call find - const std::string var(variable.substr(collection + 1)); + const auto var = variable.substr(collection + 1); if (comp(col, "ARGS")) { vv = t->m_variableArgs.resolveFirst(var); } else if (comp(variable, "ARGS_NAMES")) {