mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-17 01:36:08 +03:00
Merge pull request #3233 from eduar-hte/remove-copies-pm-operator
Removed multiple heap-allocated copies in Pm::init & parse_pm_content
This commit is contained in:
commit
4951702d45
@ -219,7 +219,6 @@ OPERATORS = \
|
|||||||
operators/no_match.cc \
|
operators/no_match.cc \
|
||||||
operators/operator.cc \
|
operators/operator.cc \
|
||||||
operators/pm.cc \
|
operators/pm.cc \
|
||||||
operators/pm_f.cc \
|
|
||||||
operators/pm_from_file.cc \
|
operators/pm_from_file.cc \
|
||||||
operators/rbl.cc \
|
operators/rbl.cc \
|
||||||
operators/rsub.cc \
|
operators/rsub.cc \
|
||||||
|
@ -15,20 +15,80 @@
|
|||||||
|
|
||||||
#include "src/operators/pm.h"
|
#include "src/operators/pm.h"
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "src/operators/operator.h"
|
|
||||||
#include "src/utils/acmp.h"
|
#include "src/utils/acmp.h"
|
||||||
#include "src/utils/string.h"
|
#include "src/utils/string.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline std::string parse_pm_content(const std::string &op_parm) {
|
||||||
|
auto offset = op_parm.find_first_not_of(" \t");
|
||||||
|
if (offset == std::string::npos) {
|
||||||
|
return op_parm;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size = op_parm.size() - offset;
|
||||||
|
if (size >= 2 &&
|
||||||
|
op_parm.at(offset) == '\"' && op_parm.back() == '\"') {
|
||||||
|
offset++;
|
||||||
|
size -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return op_parm;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string parsed_parm(op_parm.c_str() + offset, size);
|
||||||
|
|
||||||
|
unsigned char bin_offset = 0;
|
||||||
|
unsigned char bin_parm[3] = { 0 };
|
||||||
|
bool bin = false, esc = false;
|
||||||
|
|
||||||
|
char *d = parsed_parm.data();
|
||||||
|
for(const char *s = d, *e = d + size; s != e; ++s) {
|
||||||
|
if (*s == '|') {
|
||||||
|
bin = !bin;
|
||||||
|
} else if(!esc && *s == '\\') {
|
||||||
|
esc = true;
|
||||||
|
} else {
|
||||||
|
if (bin) {
|
||||||
|
if (VALID_HEX(*s)) {
|
||||||
|
bin_parm[bin_offset] = (char)*s;
|
||||||
|
bin_offset++;
|
||||||
|
if (bin_offset == 2) {
|
||||||
|
unsigned char c = strtol((char *)bin_parm, (char **) nullptr, 16) & 0xFF;
|
||||||
|
bin_offset = 0;
|
||||||
|
*d++ = c;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Invalid hex character
|
||||||
|
return op_parm;
|
||||||
|
}
|
||||||
|
} else if (esc) {
|
||||||
|
if (*s == ':' ||
|
||||||
|
*s == ';' ||
|
||||||
|
*s == '\\' ||
|
||||||
|
*s == '\"')
|
||||||
|
{
|
||||||
|
*d++ = *s;
|
||||||
|
} else {
|
||||||
|
// Unsupported escape sequence
|
||||||
|
return op_parm;
|
||||||
|
}
|
||||||
|
esc = false;
|
||||||
|
} else {
|
||||||
|
*d++ = *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed_parm.resize(d - parsed_parm.c_str());
|
||||||
|
return parsed_parm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace modsecurity {
|
namespace modsecurity {
|
||||||
namespace operators {
|
namespace operators {
|
||||||
|
|
||||||
@ -105,36 +165,19 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule,
|
|||||||
|
|
||||||
|
|
||||||
bool Pm::init(const std::string &file, std::string *error) {
|
bool Pm::init(const std::string &file, std::string *error) {
|
||||||
std::vector<std::string> vec;
|
const auto op_parm = parse_pm_content(m_param);
|
||||||
std::istringstream *iss;
|
|
||||||
const char *err = NULL;
|
|
||||||
|
|
||||||
char *content = parse_pm_content(m_param.c_str(), m_param.length(), &err);
|
std::istringstream iss{op_parm};
|
||||||
if (content == NULL) {
|
std::for_each(std::istream_iterator<std::string>(iss),
|
||||||
iss = new std::istringstream(m_param);
|
|
||||||
} else {
|
|
||||||
iss = new std::istringstream(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::copy(std::istream_iterator<std::string>(*iss),
|
|
||||||
std::istream_iterator<std::string>(),
|
std::istream_iterator<std::string>(),
|
||||||
back_inserter(vec));
|
[this](const auto &a) {
|
||||||
|
|
||||||
for (auto &a : vec) {
|
|
||||||
acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length());
|
acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length());
|
||||||
}
|
});
|
||||||
|
|
||||||
while (m_p->is_failtree_done == 0) {
|
while (m_p->is_failtree_done == 0) {
|
||||||
acmp_prepare(m_p);
|
acmp_prepare(m_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content) {
|
|
||||||
free(content);
|
|
||||||
content = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete iss;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#define SRC_OPERATORS_PM_H_
|
#define SRC_OPERATORS_PM_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* ModSecurity, http://www.modsecurity.org/
|
|
||||||
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
|
||||||
*
|
|
||||||
* You may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* If any of the files related to licensing are missing or if you have any
|
|
||||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
|
||||||
* directly using the email address security@modsecurity.org.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "src/operators/pm_f.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "src/operators/pm_from_file.h"
|
|
||||||
|
|
||||||
namespace modsecurity {
|
|
||||||
namespace operators {
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace operators
|
|
||||||
} // namespace modsecurity
|
|
@ -33,136 +33,9 @@
|
|||||||
* that should be mitigated. This ACMP parser should be re-written to
|
* that should be mitigated. This ACMP parser should be re-written to
|
||||||
* consume less memory.
|
* consume less memory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
char *parse_pm_content(const char *op_parm, unsigned short int op_len, const char **error_msg) {
|
|
||||||
char *parm = NULL;
|
|
||||||
char *content;
|
|
||||||
unsigned short int offset = 0;
|
|
||||||
// char converted = 0;
|
|
||||||
int i, x;
|
|
||||||
unsigned char bin = 0, esc = 0, bin_offset = 0;
|
|
||||||
unsigned char c = 0;
|
|
||||||
unsigned char bin_parm[3] = { 0 };
|
|
||||||
char *processed = NULL;
|
|
||||||
|
|
||||||
content = strdup(op_parm);
|
|
||||||
|
|
||||||
if (content == NULL) {
|
|
||||||
*error_msg = std::string("Error allocating memory for pattern matching content.").c_str();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (offset < op_len && (content[offset] == ' ' || content[offset] == '\t')) {
|
|
||||||
offset++;
|
|
||||||
};
|
|
||||||
|
|
||||||
op_len = strlen(content);
|
|
||||||
|
|
||||||
if (content[offset] == '\"' && content[op_len-1] == '\"') {
|
|
||||||
parm = strdup(content + offset + 1);
|
|
||||||
if (parm == NULL) {
|
|
||||||
*error_msg = std::string("Error allocating memory for pattern matching content.").c_str();
|
|
||||||
free(content);
|
|
||||||
content = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
parm[op_len - offset - 2] = '\0';
|
|
||||||
} else {
|
|
||||||
parm = strdup(content + offset);
|
|
||||||
if (parm == NULL) {
|
|
||||||
free(content);
|
|
||||||
content = NULL;
|
|
||||||
*error_msg = std::string("Error allocating memory for pattern matching content.").c_str();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(content);
|
|
||||||
content = NULL;
|
|
||||||
|
|
||||||
op_len = strlen(parm);
|
|
||||||
|
|
||||||
if (op_len == 0) {
|
|
||||||
*error_msg = "Content length is 0.";
|
|
||||||
free(parm);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, x = 0; i < op_len; i++) {
|
|
||||||
if (parm[i] == '|') {
|
|
||||||
if (bin) {
|
|
||||||
bin = 0;
|
|
||||||
} else {
|
|
||||||
bin = 1;
|
|
||||||
}
|
|
||||||
} else if(!esc && parm[i] == '\\') {
|
|
||||||
esc = 1;
|
|
||||||
} else {
|
|
||||||
if (bin) {
|
|
||||||
if (parm[i] == 0 || parm[i] == 1 || parm[i] == 2 ||
|
|
||||||
parm[i] == 3 || parm[i] == 4 || parm[i] == 5 ||
|
|
||||||
parm[i] == 6 || parm[i] == 7 || parm[i] == 8 ||
|
|
||||||
parm[i] == 9 ||
|
|
||||||
parm[i] == 'A' || parm[i] == 'a' ||
|
|
||||||
parm[i] == 'B' || parm[i] == 'b' ||
|
|
||||||
parm[i] == 'C' || parm[i] == 'c' ||
|
|
||||||
parm[i] == 'D' || parm[i] == 'd' ||
|
|
||||||
parm[i] == 'E' || parm[i] == 'e' ||
|
|
||||||
parm[i] == 'F' || parm[i] == 'f')
|
|
||||||
{
|
|
||||||
bin_parm[bin_offset] = (char)parm[i];
|
|
||||||
bin_offset++;
|
|
||||||
if (bin_offset == 2) {
|
|
||||||
c = strtol((char *)bin_parm, (char **) NULL, 16) & 0xFF;
|
|
||||||
bin_offset = 0;
|
|
||||||
parm[x] = c;
|
|
||||||
x++;
|
|
||||||
//converted = 1;
|
|
||||||
}
|
|
||||||
} else if (parm[i] == ' ') {
|
|
||||||
}
|
|
||||||
} else if (esc) {
|
|
||||||
if (parm[i] == ':' ||
|
|
||||||
parm[i] == ';' ||
|
|
||||||
parm[i] == '\\' ||
|
|
||||||
parm[i] == '\"')
|
|
||||||
{
|
|
||||||
parm[x] = parm[i];
|
|
||||||
x++;
|
|
||||||
} else {
|
|
||||||
*error_msg = std::string("Unsupported escape sequence.").c_str();
|
|
||||||
free(parm);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
esc = 0;
|
|
||||||
//converted = 1;
|
|
||||||
} else {
|
|
||||||
parm[x] = parm[i];
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (converted) {
|
|
||||||
op_len = x;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//processed = memcpy(processed, parm, op_len);
|
|
||||||
processed = strdup(parm);
|
|
||||||
free(parm);
|
|
||||||
parm = NULL;
|
|
||||||
|
|
||||||
if (processed == NULL) {
|
|
||||||
*error_msg = std::string("Error allocating memory for pattern matching content.").c_str();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return processed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -189,8 +190,6 @@ int acmp_process_quick(ACMPT *acmpt, const char **match, const char *data, size_
|
|||||||
*/
|
*/
|
||||||
int acmp_prepare(ACMP *parser);
|
int acmp_prepare(ACMP *parser);
|
||||||
|
|
||||||
char *parse_pm_content(const char *op_parm, unsigned short int op_len, const char **error_msg);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*ACMP_H_*/
|
#endif /*ACMP_H_*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user