Fixes regarding memory management

Fixes assorted issues identified by valgrind.
This commit is contained in:
Felipe Zimmerle 2016-06-15 23:52:26 -03:00
parent cb91af537c
commit 9919026620
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
46 changed files with 234 additions and 73 deletions

View File

@ -37,7 +37,7 @@ MAINTAINERCLEANFILES = \
depcomp depcomp
@VALGRIND_CHECK_RULES@ @VALGRIND_CHECK_RULES@
VALGRIND_SUPPRESSIONS_FILES = test/valgrind_suppressions.txt VALGRIND_SUPPRESSIONS_FILES = valgrind_suppressions.txt
LOG_DRIVER = env $(SHELL) $(top_srcdir)/test/custom-test-driver LOG_DRIVER = env $(SHELL) $(top_srcdir)/test/custom-test-driver
AM_TESTS_ENVIRONMENT=AUTOMAKE_TESTS=true; export AUTOMAKE_TESTS; AM_TESTS_ENVIRONMENT=AUTOMAKE_TESTS=true; export AUTOMAKE_TESTS;

View File

@ -201,7 +201,7 @@ VALGRIND_TESTS_ENVIRONMENT = \
G_SLICE=always-malloc,debug-blocks \ G_SLICE=always-malloc,debug-blocks \
G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly
VALGRIND_LOG_COMPILER = test/test-suite.sh VALGRIND_LOG_COMPILER = test/test-suite.sh $(VALGRIND_SUPPRESSIONS) $(VALGRIND_FLAGS)
# $(valgrind_lt) \ # $(valgrind_lt) \
# $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) # $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS)

View File

@ -39,6 +39,7 @@ namespace collection {
class Collection { class Collection {
public: public:
virtual ~Collection() { };
virtual void store(std::string key, std::string value) = 0; virtual void store(std::string key, std::string value) = 0;
virtual bool storeOrUpdateFirst(const std::string &key, virtual bool storeOrUpdateFirst(const std::string &key,

View File

@ -36,7 +36,7 @@ class DebugLog {
: m_debugLevel(-1), : m_debugLevel(-1),
m_fileName("") { } m_fileName("") { }
~DebugLog(); virtual ~DebugLog();
virtual void write(int level, const std::string &msg); virtual void write(int level, const std::string &msg);
bool isLogFileSet(); bool isLogFileSet();

View File

@ -103,7 +103,7 @@ class RulesProperties {
*/ */
~RulesProperties() { ~RulesProperties() {
delete m_debugLog; delete m_debugLog;
} };
std::vector<Rule *> rules[7]; std::vector<Rule *> rules[7];
std::vector<Rule *> * getRulesForPhase(int phase) { std::vector<Rule *> * getRulesForPhase(int phase) {

View File

@ -51,6 +51,7 @@ Collections::~Collections() {
for (const auto &thing : *this) { for (const auto &thing : *this) {
delete thing.second; delete thing.second;
} }
delete m_transient;
this->clear(); this->clear();
} }

View File

@ -40,17 +40,16 @@ void DebugLogWriter::open(const std::string& fileName) {
void DebugLogWriter::close(const std::string& fileName) { void DebugLogWriter::close(const std::string& fileName) {
#if 0
std::map<std::string, DebugLogWriterAgent *>::iterator it; std::map<std::string, DebugLogWriterAgent *>::iterator it;
DebugLogWriterAgent *agent; DebugLogWriterAgent *agent;
it = agents.find(fileName); it = agents.find(fileName);
if (it != agents.end()) { if (it != agents.end()) {
agent = it->second; agent = it->second;
if (agent->refCountDecreaseAndCheck()) { if (agent->refCountDecreaseAndCheck()) {
delete agent;
agents.erase(it); agents.erase(it);
} }
} }
#endif
} }

View File

@ -33,7 +33,6 @@ DebugLogWriterAgent::DebugLogWriterAgent(const std::string& fileName) :
void DebugLogWriterAgent::write(const std::string& msg) { void DebugLogWriterAgent::write(const std::string& msg) {
if (!is_open()) { if (!is_open()) {
std::cout << "Agent: " << m_fileName << ": " << msg << std::endl;
return; return;
} }

View File

@ -36,7 +36,6 @@ class DebugLogWriterAgent : public std::ofstream {
bool refCountDecreaseAndCheck() { bool refCountDecreaseAndCheck() {
this->m_referenceCount--; this->m_referenceCount--;
if (this->m_referenceCount == 0) { if (this->m_referenceCount == 0) {
delete this;
return true; return true;
} }
return false; return false;

View File

@ -66,6 +66,10 @@ ModSecurity::~ModSecurity() {
#ifdef WITH_GEOIP #ifdef WITH_GEOIP
Utils::GeoLookup::getInstance().cleanUp(); Utils::GeoLookup::getInstance().cleanUp();
#endif #endif
delete m_global_collection;
delete m_ip_collection;
delete m_session_collection;
delete m_user_collection;
} }

View File

@ -25,12 +25,12 @@ namespace modsecurity {
namespace operators { namespace operators {
bool IpMatch::init(const std::string &file, const char **error) { bool IpMatch::init(const std::string &file, std::string *error) {
std::string e(""); std::string e("");
bool res = m_tree.addFromBuffer(param, &e); bool res = m_tree.addFromBuffer(param, &e);
if (res == false) { if (res == false) {
*error = e.c_str(); error->assign(e);
} }
return res; return res;

View File

@ -33,7 +33,7 @@ class IpMatch : public Operator {
bool evaluate(Transaction *transaction, const std::string &input) override; bool evaluate(Transaction *transaction, const std::string &input) override;
bool init(const std::string &file, const char **error) override; bool init(const std::string &file, std::string *error) override;
protected: protected:
Utils::IpTree m_tree; Utils::IpTree m_tree;

View File

@ -15,6 +15,8 @@
#include "operators/ip_match_from_file.h" #include "operators/ip_match_from_file.h"
#include <string.h>
#include <string> #include <string>
#include "operators/operator.h" #include "operators/operator.h"
@ -24,7 +26,7 @@ namespace operators {
bool IpMatchFromFile::init(const std::string &file, bool IpMatchFromFile::init(const std::string &file,
const char **error) { std::string *error) {
std::string e(""); std::string e("");
bool res = false; bool res = false;
@ -35,7 +37,7 @@ bool IpMatchFromFile::init(const std::string &file,
} }
if (res == false) { if (res == false) {
*error = e.c_str(); error->assign(e);
} }
return res; return res;

View File

@ -29,7 +29,7 @@ class IpMatchFromFile : public IpMatch {
IpMatchFromFile(std::string op, std::string param, bool negation) IpMatchFromFile(std::string op, std::string param, bool negation)
: IpMatch(op, param, negation) { } : IpMatch(op, param, negation) { }
bool init(const std::string& file, const char **error) override; bool init(const std::string& file, std::string *error) override;
}; };
} // namespace operators } // namespace operators

View File

@ -40,7 +40,7 @@ class Operator {
std::string param; std::string param;
bool negation; bool negation;
virtual bool init(const std::string &file, const char **error) { virtual bool init(const std::string &file, std::string *error) {
return true; return true;
} }

View File

@ -85,13 +85,14 @@ bool Pm::evaluate(Transaction *transaction, const std::string &input) {
} }
bool Pm::init(const std::string &file, const char **error) { bool Pm::init(const std::string &file, std::string *error) {
std::vector<std::string> vec; std::vector<std::string> vec;
std::istringstream *iss; std::istringstream *iss;
const char *err = NULL;
replaceAll(param, "\\", "\\\\"); replaceAll(param, "\\", "\\\\");
char *content = parse_pm_content(param.c_str(), param.length(), error); char *content = parse_pm_content(param.c_str(), param.length(), &err);
if (content == NULL) { if (content == NULL) {
iss = new std::istringstream(param); iss = new std::istringstream(param);
} else { } else {

View File

@ -39,7 +39,7 @@ class Pm : public Operator {
const std::string& to); const std::string& to);
bool evaluate(Transaction *transaction, const std::string &input) override; bool evaluate(Transaction *transaction, const std::string &input) override;
bool init(const std::string &file, const char **error) override; bool init(const std::string &file, std::string *error) override;
void postOrderTraversal(acmp_btree_node_t *node); void postOrderTraversal(acmp_btree_node_t *node);
protected: protected:

View File

@ -25,14 +25,14 @@ namespace modsecurity {
namespace operators { namespace operators {
bool PmFromFile::init(const std::string &config, const char **error) { bool PmFromFile::init(const std::string &config, std::string *error) {
std::istream *iss; std::istream *iss;
if (param.compare(0, 8, "https://") == 0) { if (param.compare(0, 8, "https://") == 0) {
Utils::HttpsClient client; Utils::HttpsClient client;
bool ret = client.download(param); bool ret = client.download(param);
if (ret == false) { if (ret == false) {
*error = client.error.c_str(); error->assign(client.error);
return false; return false;
} }
iss = new std::stringstream(client.content); iss = new std::stringstream(client.content);
@ -41,7 +41,7 @@ bool PmFromFile::init(const std::string &config, const char **error) {
iss = new std::ifstream(resource, std::ios::in); iss = new std::ifstream(resource, std::ios::in);
if (((std::ifstream *)iss)->is_open() == false) { if (((std::ifstream *)iss)->is_open() == false) {
*error = std::string("Failed to open file: " + param).c_str(); error->assign("Failed to open file: " + param);
delete iss; delete iss;
return false; return false;
} }
@ -51,7 +51,7 @@ bool PmFromFile::init(const std::string &config, const char **error) {
acmp_add_pattern(m_p, line.c_str(), NULL, NULL, line.length()); acmp_add_pattern(m_p, line.c_str(), NULL, NULL, line.length());
} }
acmp_prepare(m_p); //acmp_prepare(m_p);
delete iss; delete iss;
return true; return true;

View File

@ -31,7 +31,7 @@ class PmFromFile : public Pm {
PmFromFile(std::string op, std::string param, bool negation) PmFromFile(std::string op, std::string param, bool negation)
: Pm(op, param, negation) { } : Pm(op, param, negation) { }
bool init(const std::string &file, const char **error) override; bool init(const std::string &file, std::string *error) override;
}; };

View File

@ -40,6 +40,9 @@ class Rx : public Operator {
m_re = new Regex(param); m_re = new Regex(param);
} }
~Rx() {
delete m_re;
}
bool evaluate(Transaction *transaction, const std::string &input); bool evaluate(Transaction *transaction, const std::string &input);
private: private:

View File

@ -23,7 +23,7 @@ namespace modsecurity {
namespace operators { namespace operators {
bool ValidateByteRange::getRange(const std::string &rangeRepresentation, bool ValidateByteRange::getRange(const std::string &rangeRepresentation,
const char **error) { std::string *error) {
size_t pos = param.find_first_of("-"); size_t pos = param.find_first_of("-");
int start; int start;
int end; int end;
@ -32,8 +32,8 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation,
try { try {
start = std::stoi(rangeRepresentation); start = std::stoi(rangeRepresentation);
} catch(...) { } catch(...) {
*error = ("Not able to convert '" + rangeRepresentation + error->assign("Not able to convert '" + rangeRepresentation +
"' into a number").c_str(); "' into a number");
return false; return false;
} }
table[start >> 3] = (table[start >> 3] | (1 << (start & 0x7))); table[start >> 3] = (table[start >> 3] | (1 << (start & 0x7)));
@ -43,9 +43,9 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation,
try { try {
start = std::stoi(std::string(rangeRepresentation, 0, pos)); start = std::stoi(std::string(rangeRepresentation, 0, pos));
} catch (...) { } catch (...) {
*error = ("Not able to convert '" + error->assign("Not able to convert '" +
std::string(rangeRepresentation, 0, pos) + std::string(rangeRepresentation, 0, pos) +
"' into a number").c_str(); "' into a number");
return false; return false;
} }
@ -53,24 +53,24 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation,
end = std::stoi(std::string(rangeRepresentation, pos + 1, end = std::stoi(std::string(rangeRepresentation, pos + 1,
rangeRepresentation.length() - (pos + 1))); rangeRepresentation.length() - (pos + 1)));
} catch (...) { } catch (...) {
*error = ("Not able to convert '" + std::string(rangeRepresentation, error->assign("Not able to convert '" + std::string(rangeRepresentation,
pos + 1, rangeRepresentation.length() - (pos + 1)) + pos + 1, rangeRepresentation.length() - (pos + 1)) +
"' into a number").c_str(); "' into a number");
return false; return false;
} }
if ((start < 0) || (start > 255)) { if ((start < 0) || (start > 255)) {
*error = ("Invalid range start value: " + error->assign("Invalid range start value: " +
std::to_string(start)).c_str(); std::to_string(start));
return false; return false;
} }
if ((end < 0) || (end > 255)) { if ((end < 0) || (end > 255)) {
*error = ("Invalid range end value: " + std::to_string(end)).c_str(); error->assign("Invalid range end value: " + std::to_string(end));
return false; return false;
} }
if (start > end) { if (start > end) {
*error = ("Invalid range: " + std::to_string(start) + "-" + error->assign("Invalid range: " + std::to_string(start) + "-" +
std::to_string(end)).c_str(); std::to_string(end));
return false; return false;
} }
@ -84,7 +84,7 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation,
bool ValidateByteRange::init(const std::string &file, bool ValidateByteRange::init(const std::string &file,
const char **error) { std::string *error) {
size_t pos = param.find_first_of(","); size_t pos = param.find_first_of(",");
if (pos == std::string::npos) { if (pos == std::string::npos) {

View File

@ -37,8 +37,8 @@ class ValidateByteRange : public Operator {
~ValidateByteRange() override { } ~ValidateByteRange() override { }
bool evaluate(Transaction *transaction, const std::string &input) override; bool evaluate(Transaction *transaction, const std::string &input) override;
bool getRange(const std::string &rangeRepresentation, const char **error); bool getRange(const std::string &rangeRepresentation, std::string *error);
bool init(const std::string& file, const char **error) override; bool init(const std::string& file, std::string *error) override;
private: private:
std::vector<std::string> ranges; std::vector<std::string> ranges;
char table[32]; char table[32];

View File

@ -25,11 +25,10 @@ namespace modsecurity {
namespace operators { namespace operators {
bool ValidateDTD::init(const std::string &file, const char **error) { bool ValidateDTD::init(const std::string &file, std::string *error) {
m_resource = find_resource(param, file); m_resource = find_resource(param, file);
if (m_resource == "") { if (m_resource == "") {
std::string f("XML: File not found: " + param + "."); error->assign("XML: File not found: " + param + ".");
*error = strdup(f.c_str());
return false; return false;
} }

View File

@ -44,7 +44,7 @@ class ValidateDTD : public Operator {
} }
bool evaluate(Transaction *transaction, const std::string &str) override; bool evaluate(Transaction *transaction, const std::string &str) override;
bool init(const std::string &file, const char **error) override; bool init(const std::string &file, std::string *error) override;
static void error_runtime(void *ctx, const char *msg, ...) { static void error_runtime(void *ctx, const char *msg, ...) {

View File

@ -25,11 +25,10 @@
namespace modsecurity { namespace modsecurity {
namespace operators { namespace operators {
bool ValidateSchema::init(const std::string &file, const char **error) { bool ValidateSchema::init(const std::string &file, std::string *error) {
m_resource = find_resource(param, file); m_resource = find_resource(param, file);
if (m_resource == "") { if (m_resource == "") {
std::string f("XML: File not found: " + param + "."); error->assign("XML: File not found: " + param + ".");
*error = strdup(f.c_str());
return false; return false;
} }

View File

@ -52,7 +52,7 @@ class ValidateSchema : public Operator {
} }
bool evaluate(Transaction *transaction, const std::string &str) override; bool evaluate(Transaction *transaction, const std::string &str) override;
bool init(const std::string &file, const char **error) override; bool init(const std::string &file, std::string *error) override;
static void error_load(void *ctx, const char *msg, ...) { static void error_load(void *ctx, const char *msg, ...) {

View File

@ -69,7 +69,7 @@ int VerifyCC::luhnVerify(const char *ccnumber, int len) {
bool VerifyCC::init(const std::string &param2, const char **error) { bool VerifyCC::init(const std::string &param2, std::string *error) {
const char *errptr = NULL; const char *errptr = NULL;
int erroffset = 0; int erroffset = 0;
@ -78,7 +78,7 @@ bool VerifyCC::init(const std::string &param2, const char **error) {
m_pce = pcre_study(m_pc, PCRE_STUDY_JIT_COMPILE, &errptr); m_pce = pcre_study(m_pc, PCRE_STUDY_JIT_COMPILE, &errptr);
if ((m_pc == NULL) || (m_pce == NULL)) { if ((m_pc == NULL) || (m_pce == NULL)) {
*error = errptr; error->assign(errptr);
return false; return false;
} }

View File

@ -34,7 +34,7 @@ class VerifyCC : public Operator {
int luhnVerify(const char *ccnumber, int len); int luhnVerify(const char *ccnumber, int len);
bool evaluate(Transaction *transaction, const std::string &input) override; bool evaluate(Transaction *transaction, const std::string &input) override;
bool init(const std::string &param, const char **error) override; bool init(const std::string &param, std::string *error) override;
private: private:
pcre *m_pc; pcre *m_pc;
pcre_extra *m_pce; pcre_extra *m_pce;

View File

@ -429,7 +429,7 @@ op:
OPERATOR OPERATOR
{ {
Operator *op = Operator::instantiate($1); Operator *op = Operator::instantiate($1);
const char *error = NULL; std::string error;
if (op->init(driver.ref.back(), &error) == false) { if (op->init(driver.ref.back(), &error) == false) {
driver.error(@0, error); driver.error(@0, error);
YYERROR; YYERROR;
@ -440,7 +440,7 @@ op:
{ {
#ifdef WITH_GEOIP #ifdef WITH_GEOIP
Operator *op = Operator::instantiate($1); Operator *op = Operator::instantiate($1);
const char *error = NULL; std::string error;
if (op->init(driver.ref.back(), &error) == false) { if (op->init(driver.ref.back(), &error) == false) {
driver.error(@0, error); driver.error(@0, error);
YYERROR; YYERROR;
@ -459,7 +459,7 @@ op:
text.pop_back(); text.pop_back();
text.erase(0, 1); text.erase(0, 1);
Operator *op = Operator::instantiate("\"@rx " + text + "\""); Operator *op = Operator::instantiate("\"@rx " + text + "\"");
const char *error = NULL; std::string error;
if (op->init(driver.ref.back(), &error) == false) { if (op->init(driver.ref.back(), &error) == false) {
driver.error(@0, error); driver.error(@0, error);
YYERROR; YYERROR;

View File

@ -92,9 +92,17 @@ Multipart::~Multipart() {
} }
} }
while (!m_parts.empty()) { while (m_parts.empty() == false) {
m_parts.pop_front(); auto *a = m_parts.back();
m_parts.pop_back();
delete a;
} }
if (m_mpp != NULL) {
delete m_mpp;
m_mpp = NULL;
}
} }
@ -734,9 +742,13 @@ int Multipart::process_part_header() {
return false; return false;
} }
m_mpp->m_headers.insert({header_name, header_value});
m_mpp->m_last_header_name.assign(header_name); m_mpp->m_last_header_name.assign(header_name);
m_mpp->m_headers.emplace(
std::string(header_name), std::string(header_value));
debug(9, "Multipart: Added part header \"" + header_name \ debug(9, "Multipart: Added part header \"" + header_name \
+ "\" \"" + header_value + "\"."); + "\" \"" + header_value + "\".");
} }
@ -784,6 +796,7 @@ int Multipart::process_boundary(int last_part) {
debug(3, "Multipart: Skipping invalid part (part name missing): " debug(3, "Multipart: Skipping invalid part (part name missing): "
"(offset " + std::to_string(m_mpp->m_offset) + ", length " "(offset " + std::to_string(m_mpp->m_offset) + ", length "
+ std::to_string(m_mpp->m_length) + ")"); + std::to_string(m_mpp->m_length) + ")");
delete m_mpp;
} }
m_mpp = NULL; m_mpp = NULL;

View File

@ -54,13 +54,18 @@ struct MyEqual {
class MultipartPart { class MultipartPart {
public: public:
MultipartPart() MultipartPart()
: m_type(MULTIPART_FORMDATA), : m_type(MULTIPART_FORMDATA),
m_tmp_file_fd(0), m_tmp_file_fd(0),
m_tmp_file_size(0), m_tmp_file_size(0),
m_offset(0), m_offset(0),
m_length(0) { } m_length(0) { }
~MultipartPart () {
m_headers.clear();
m_value_parts.clear();
}
/* part type, can be MULTIPART_FORMDATA or MULTIPART_FILE */ /* part type, can be MULTIPART_FORMDATA or MULTIPART_FILE */
int m_type; int m_type;

View File

@ -309,6 +309,7 @@ bool Rule::evaluate(Transaction *trasn) {
variable->evaluateInternal(trasn, this, &z); variable->evaluateInternal(trasn, 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(variable->m_name); exclusions.push_back(variable->m_name);
} }

View File

@ -78,6 +78,8 @@ void Rules::decrementReferenceCount(void) {
Rules::~Rules() { Rules::~Rules() {
int i = 0;
/** Cleanup the rules */ /** Cleanup the rules */
for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) { for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
std::vector<Rule *> rules = this->rules[i]; std::vector<Rule *> rules = this->rules[i];
@ -87,10 +89,20 @@ Rules::~Rules() {
rules.pop_back(); rules.pop_back();
} }
} }
for (i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
std::vector<actions::Action *> *tmp = &defaultActions[i];
while (tmp->empty() == false) {
actions::Action *a = tmp->back();
tmp->pop_back();
delete a;
}
}
/** Cleanup audit log */ /** Cleanup audit log */
if (audit_log) { if (audit_log) {
audit_log->refCountDecreaseAndCheck(); audit_log->refCountDecreaseAndCheck();
} }
free(unicode_map_table);
} }
@ -128,6 +140,7 @@ int Rules::load(const char *file, const std::string &ref) {
if (driver->parse(file, ref) == false) { if (driver->parse(file, ref) == false) {
parserError << driver->parserError.str(); parserError << driver->parserError.str();
delete driver;
return -1; return -1;
} }
int rules = this->merge(driver); int rules = this->merge(driver);

View File

@ -1395,6 +1395,7 @@ std::string Transaction::toJSON(int parts) {
m_collections.m_transient->resolveMultiMatches("REQUEST_HEADERS", &l); m_collections.m_transient->resolveMultiMatches("REQUEST_HEADERS", &l);
for (auto h : l) { for (auto h : l) {
LOGFY_ADD(h->m_key.c_str(), h->m_value.c_str()); LOGFY_ADD(h->m_key.c_str(), h->m_value.c_str());
delete h;
} }
/* end: request headers */ /* end: request headers */
@ -1424,6 +1425,7 @@ std::string Transaction::toJSON(int parts) {
m_collections.m_transient->resolveMultiMatches("RESPONSE_HEADERS", &l); m_collections.m_transient->resolveMultiMatches("RESPONSE_HEADERS", &l);
for (auto h : l) { for (auto h : l) {
LOGFY_ADD(h->m_key.c_str(), h->m_value.c_str()); LOGFY_ADD(h->m_key.c_str(), h->m_value.c_str());
delete h;
} }
/* end: response headers */ /* end: response headers */

View File

@ -569,4 +569,4 @@ int acmp_process_quick(ACMPT *acmpt, const char **match, const char *data, size_
return 0; return 0;
} }
} }

View File

@ -39,50 +39,57 @@ void IpTree::postOrderTraversal(TreeNode *node) {
postOrderTraversal(node->right); postOrderTraversal(node->right);
if (node->netmasks) { if (node->netmasks) {
delete node->netmasks; free(node->netmasks);
node->netmasks = NULL; node->netmasks = NULL;
} }
if (node->prefix) { if (node->prefix) {
if (node->prefix->buffer) { if (node->prefix->buffer) {
delete node->prefix->buffer; free(node->prefix->buffer);
node->prefix->buffer = NULL; node->prefix->buffer = NULL;
} }
if (node->prefix->prefix_data) { if (node->prefix->prefix_data) {
delete node->prefix->prefix_data; free(node->prefix->prefix_data);
node->prefix->prefix_data = NULL; node->prefix->prefix_data = NULL;
} }
delete node->prefix; free(node->prefix);
node->prefix = NULL; node->prefix = NULL;
} }
delete node; free(node);
node = NULL; node = NULL;
} }
IpTree::IpTree() {
// FIXME: deal with possible error.
char *error;
create_radix_tree(&m_tree, &error);
}
IpTree::~IpTree() { IpTree::~IpTree() {
if (m_tree != NULL) { if (m_tree != NULL) {
if (m_tree->ipv4_tree != NULL) { if (m_tree->ipv4_tree != NULL) {
// Tree_traversal: Post-order to delete all the items. // Tree_traversal: Post-order to delete all the items.
postOrderTraversal(m_tree->ipv4_tree->head); postOrderTraversal(m_tree->ipv4_tree->head);
delete m_tree->ipv4_tree; free(m_tree->ipv4_tree);
m_tree->ipv4_tree = NULL; m_tree->ipv4_tree = NULL;
} }
if (m_tree->ipv6_tree != NULL) { if (m_tree->ipv6_tree != NULL) {
// Tree_traversal: Post-order to delete all the items. // Tree_traversal: Post-order to delete all the items.
postOrderTraversal(m_tree->ipv6_tree->head); postOrderTraversal(m_tree->ipv6_tree->head);
delete m_tree->ipv6_tree; free(m_tree->ipv6_tree);
m_tree->ipv6_tree = NULL; m_tree->ipv6_tree = NULL;
} }
delete m_tree; free(m_tree);
m_tree = NULL; m_tree = NULL;
} }
} }
bool IpTree::addFromBuffer(std::istream *ss, std::string *error) { bool IpTree::addFromBuffer(std::istream *ss, std::string *error) {
char *error_msg = NULL; char *error_msg = NULL;
for (std::string line; std::getline(*ss, line); ) { for (std::string line; std::getline(*ss, line); ) {
int res = ip_tree_from_param(line.c_str(), &m_tree, &error_msg); int res = add_ip_from_param(line.c_str(), &m_tree, &error_msg);
if (res != 0) { if (res != 0) {
if (error_msg != NULL) { if (error_msg != NULL) {
error->assign(error_msg); error->assign(error_msg);
@ -98,7 +105,6 @@ bool IpTree::addFromBuffer(std::istream *ss, std::string *error) {
bool IpTree::addFromBuffer(const std::string& buffer, std::string *error) { bool IpTree::addFromBuffer(const std::string& buffer, std::string *error) {
std::stringstream ss; std::stringstream ss;
ss << buffer; ss << buffer;
return addFromBuffer(&ss, error); return addFromBuffer(&ss, error);
} }

View File

@ -30,8 +30,7 @@ namespace Utils {
class IpTree { class IpTree {
public: public:
IpTree() IpTree();
: m_tree(NULL) { }
~IpTree(); ~IpTree();
bool contains(const std::string &ip); bool contains(const std::string &ip);

View File

@ -958,6 +958,44 @@ int tree_contains_ip(TreeRoot *rtree,
return 0; return 0;
} }
int add_ip_from_param(
const char *param, TreeRoot **rtree, char **error_msg)
{
char *param_copy = strdup(param);
char *saved = NULL;
char *str = NULL;
TreeNode *tnode = NULL;
str = strtok_r(param_copy, ",", &saved);
while (str != NULL)
{
if (strchr(str, ':') == NULL)
{
tnode = TreeAddIP(str, (*rtree)->ipv4_tree, IPV4_TREE);
}
else
{
tnode = TreeAddIP(str, (*rtree)->ipv6_tree, IPV6_TREE);
}
if (tnode == NULL)
{
//*error_msg = apr_psprintf("Could not add entry " \
// "\"%s\" from: %s.", str, param);
free(param_copy);
return -1;
}
str = strtok_r(NULL, ",", &saved);
}
free(param_copy);
return 0;
}
int ip_tree_from_param( int ip_tree_from_param(
const char *param, TreeRoot **rtree, char **error_msg) const char *param, TreeRoot **rtree, char **error_msg)
{ {

View File

@ -97,6 +97,7 @@ unsigned char is_netmask_v6(char *ip_strv6);
int tree_contains_ip(TreeRoot *rtree, int tree_contains_ip(TreeRoot *rtree,
const char *value, char **error_msg); const char *value, char **error_msg);
int add_ip_from_param(const char *param, TreeRoot **rtree, char **error_msg);
int ip_tree_from_param(const char *param, TreeRoot **rtree, char **error_msg); int ip_tree_from_param(const char *param, TreeRoot **rtree, char **error_msg);
int create_radix_tree(TreeRoot **rtree, char **error_msg); int create_radix_tree(TreeRoot **rtree, char **error_msg);
} }

View File

@ -45,6 +45,19 @@ Regex::Regex(const std::string& pattern_)
m_pce = pcre_study(m_pc, PCRE_STUDY_JIT_COMPILE, &errptr); m_pce = pcre_study(m_pc, PCRE_STUDY_JIT_COMPILE, &errptr);
} }
Regex::~Regex() {
if (m_pc != NULL) {
pcre_free(m_pc);
m_pc = NULL;
}
if (m_pce != NULL) {
pcre_free_study(m_pce);
m_pce = NULL;
}
}
int regex_search(const std::string& s, SMatch *match, int regex_search(const std::string& s, SMatch *match,
const Regex& regex) { const Regex& regex) {
int ovector[OVECCOUNT]; int ovector[OVECCOUNT];

View File

@ -31,6 +31,7 @@ namespace Utils {
class Regex { class Regex {
public: public:
explicit Regex(const std::string& pattern_); explicit Regex(const std::string& pattern_);
~Regex();
std::string pattern; std::string pattern;
pcre *m_pc = NULL; pcre *m_pc = NULL;
pcre_extra *m_pce = NULL; pcre_extra *m_pce = NULL;

View File

@ -27,6 +27,7 @@ CustomDebugLog *CustomDebugLog::new_instance() {
return new CustomDebugLog(); return new CustomDebugLog();
} }
CustomDebugLog::~CustomDebugLog() { }
void CustomDebugLog::write(int level, const std::string& message) { void CustomDebugLog::write(int level, const std::string& message) {
m_log << "[" << level << "] " << message << std::endl; m_log << "[" << level << "] " << message << std::endl;
@ -35,7 +36,6 @@ void CustomDebugLog::write(int level, const std::string& message) {
bool CustomDebugLog::contains(const std::string& pattern) { bool CustomDebugLog::contains(const std::string& pattern) {
modsecurity::Utils::Regex re(pattern); modsecurity::Utils::Regex re(pattern);
modsecurity::Utils::SMatch match;
std::string s = m_log.str(); std::string s = m_log.str();
return modsecurity::Utils::regex_search(s, re); return modsecurity::Utils::regex_search(s, re);
} }

View File

@ -26,6 +26,7 @@ namespace modsecurity_test {
class CustomDebugLog : public modsecurity::DebugLog { class CustomDebugLog : public modsecurity::DebugLog {
public: public:
CustomDebugLog *new_instance(); CustomDebugLog *new_instance();
~CustomDebugLog();
void write(int level, const std::string& message) override; void write(int level, const std::string& message) override;
bool contains(const std::string& pattern); bool contains(const std::string& pattern);

View File

@ -134,6 +134,11 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
std::cout << KCYN << "skipped!" << RESET << std::endl; std::cout << KCYN << "skipped!" << RESET << std::endl;
} }
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
@ -156,6 +161,11 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
<< std::endl; << std::endl;
testRes->passed = false; testRes->passed = false;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
@ -174,6 +184,11 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
testRes->reason << KGRN << "passed!" << RESET << std::endl; testRes->reason << KGRN << "passed!" << RESET << std::endl;
testRes->passed = true; testRes->passed = true;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} else { } else {
/* Parser error was expected, but with a different content */ /* Parser error was expected, but with a different content */
@ -193,6 +208,11 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
<< s << std::endl; << s << std::endl;
testRes->passed = false; testRes->passed = false;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
} else { } else {
@ -210,6 +230,11 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
} }
testRes->passed = false; testRes->passed = false;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
} }
@ -340,7 +365,6 @@ after_debug_log:
int main(int argc, char **argv) { int main(int argc, char **argv) {
ModSecurityTest<RegressionTest> test; ModSecurityTest<RegressionTest> test;
ModSecurityTestResults<RegressionTest> results;
int test_number = 0; int test_number = 0;
#ifdef WITH_GEOIP #ifdef WITH_GEOIP
@ -414,6 +438,7 @@ int main(int argc, char **argv) {
} }
failed++; failed++;
} }
delete r;
} }
if (!test.m_automake_output) { if (!test.m_automake_output) {
@ -439,6 +464,7 @@ int main(int argc, char **argv) {
} }
delete vec; delete vec;
} }
#endif #endif
return 0; return 0;
} }

View File

@ -47,7 +47,7 @@ void print_help() {
void perform_unit_test(ModSecurityTest<UnitTest> *test, UnitTest *t, void perform_unit_test(ModSecurityTest<UnitTest> *test, UnitTest *t,
ModSecurityTestResults<UnitTest>* res) { ModSecurityTestResults<UnitTest>* res) {
const char *error = NULL; std::string error;
if (test->m_automake_output) { if (test->m_automake_output) {
std::cout << ":test-result: "; std::cout << ":test-result: ";

View File

@ -1,3 +1,26 @@
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:_Znwm
fun:_ZN11modsecurity9operators8Operator11instantiateENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
fun:_ZN2yy14seclang_parser5parseEv
fun:_ZN11modsecurity6Parser6Driver5parseERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_
fun:_ZN11modsecurity5Rules4loadEPKcRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
fun:_Z17perform_unit_testPN16modsecurity_test15ModSecurityTestINS_14RegressionTestEEEPSt6vectorIPS1_SaIS5_EEPNS_22ModSecurityTestResultsINS_20RegressionTestResultEEEPi
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:_Znwm
fun:_ZN2yy14seclang_parser5parseEv
fun:_ZN11modsecurity6Parser6Driver5parseERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_
fun:_ZN11modsecurity5Rules4loadEPKcRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
fun:_Z17perform_unit_testPN16modsecurity_test15ModSecurityTestINS_14RegressionTestEEEPSt6vectorIPS1_SaIS5_EEPNS_22ModSecurityTestResultsINS_20RegressionTestResultEEEPi
fun:main
}
{ {
<insert_a_suppression_name_here> <insert_a_suppression_name_here>
Memcheck:Leak Memcheck:Leak
@ -73,4 +96,16 @@
fun:_Z17perform_unit_testPSt6vectorIPN16modsecurity_test14RegressionTestESaIS2_EEPNS0_22ModSecurityTestResultsIS1_EEPi fun:_Z17perform_unit_testPSt6vectorIPN16modsecurity_test14RegressionTestESaIS2_EEPNS0_22ModSecurityTestResultsIS1_EEPi
fun:main fun:main
} }
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:_Znwm
fun:_ZN11modsecurity7actions6Action11instantiateERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
fun:_ZN2yy14seclang_parser5parseEv
fun:_ZN11modsecurity6Parser6Driver5parseERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_
fun:_ZN11modsecurity5Rules4loadEPKcRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
fun:_Z17perform_unit_testPN16modsecurity_test15ModSecurityTestINS_14RegressionTestEEEPSt6vectorIPS1_SaIS5_EEPNS_22ModSecurityTestResultsINS_20RegressionTestResultEEEPi
fun:main
}