Skip to content

Commit

Permalink
Add proper error handling to @rx operator
Browse files Browse the repository at this point in the history
  • Loading branch information
WGH- committed Sep 5, 2020
1 parent 5437b44 commit 95f16ea
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 7 deletions.
13 changes: 13 additions & 0 deletions src/operators/rx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ namespace operators {

bool Rx::init(const std::string &arg, std::string *error) {
if (m_string->m_containsMacro == false) {
std::string regex_error;
m_re = new Regex(m_param);
if (!m_re->ok(&regex_error)) {
*error = "Failed to compile regular expression " + m_re->getPattern() + ": " + regex_error;
return false;
}
}

return true;
Expand All @@ -47,6 +52,14 @@ bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule,
if (m_string->m_containsMacro) {
std::string eparam(m_string->evaluate(transaction));
re = new Regex(eparam);
std::string regex_error;
if (!re->ok(&regex_error)) {
ms_dbg_a(transaction, 2,
"Failed to compile regular expression with macro "
+ re->getPattern() + ": " + regex_error);
delete re;
return false;
}
} else {
re = m_re;
}
Expand Down
2 changes: 1 addition & 1 deletion src/regex/backend/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Backend {
public:
virtual ~Backend() {}

virtual bool ok() const = 0;
virtual bool ok(std::string *error = nullptr) const = 0;

virtual std::list<RegexMatch> searchAll(const std::string& s) const = 0;
virtual bool searchOneMatch(const std::string& s, std::vector<RegexMatchCapture>& captures) const = 0;
Expand Down
10 changes: 10 additions & 0 deletions src/regex/backend/pcre.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,18 @@ Pcre::Pcre(const std::string& pattern_)

m_pc = pcre_compile(pattern.c_str(), PCRE_DOTALL|PCRE_MULTILINE,
&errptr, &erroffset, NULL);
if (m_pc == NULL) {
m_error = "pcre_compile error at offset " + std::to_string(erroffset) + ": " + std::string(errptr);
return;
}

m_pce = pcre_study(m_pc, pcre_study_opt, &errptr);
if (m_pce == NULL) {
m_error = "pcre_study error: " + std::string(errptr);
pcre_free(m_pc);
m_pc = nullptr;
return;
}
}


Expand Down
13 changes: 11 additions & 2 deletions src/regex/backend/pcre.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,15 @@ class Pcre : public Backend {
int search(const std::string &s, RegexMatch *m) const override;
int search(const std::string &s) const override;

virtual bool ok() const override {
return m_pc != NULL;
virtual bool ok(std::string *error = nullptr) const override {
if (m_pc != NULL) {
return true;
}
if (error != nullptr) {
*error= m_error;
}

return false;
}

virtual const std::string& getPattern() const override {
Expand All @@ -64,6 +71,8 @@ class Pcre : public Backend {

pcre *m_pc = NULL;
pcre_extra *m_pce = NULL;

std::string m_error;
};

#endif
Expand Down
10 changes: 8 additions & 2 deletions src/regex/backend/re2.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,14 @@ class Re2 : public Backend {
bool searchOneMatch(const std::string& s, std::vector<RegexMatchCapture>& captures) const override;
int search(const std::string &s, RegexMatch *m) const override;
int search(const std::string &s) const override;
virtual bool ok() const override {
return re.ok();
virtual bool ok(std::string *error = nullptr) const override {
if (re.ok()) {
return true;
}
if (error != nullptr) {
*error = re.error();
}
return false;
}

virtual const std::string& getPattern() const override {
Expand Down
4 changes: 2 additions & 2 deletions src/regex/backend_fallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class BackendFallback : public backend::Backend {
: backend(compile_regex_fallback<Args...>(pattern))
{}

virtual bool ok() const override {
return backend->ok();
virtual bool ok(std::string *error = nullptr) const override {
return backend->ok(error);
}

std::list<RegexMatch> searchAll(const std::string& s) const override {
Expand Down
57 changes: 57 additions & 0 deletions test/test-cases/regression/operator-rx.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,62 @@
"SecRuleEngine On",
"SecRule REQUEST_HEADERS:Content-Length \"!^0$\" \"id:1,phase:2,pass,t:trim,block\""
]
},
{
"enabled":1,
"version_min":300000,
"version_max":0,
"title":"Testing Operator :: @rx with invalid regular expression",
"expected":{
"parser_error":"Rules error.*Failed to compile regular expression \\(\\(value1\\):"
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS \"@rx ((value1)\" \"id:1,phase:2,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing Operator :: @rx with invalid regular expression after macro expansion",
"client":{
"ip":"200.249.12.31",
"port":123
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Content-Length": "27",
"Content-Type": "application/x-www-form-urlencoded"
},
"uri":"/",
"method":"POST",
"body": [
"param1=value1&param2=value2"
]
},
"response":{
"headers":{
"Date":"Mon, 13 Jul 2015 20:02:41 GMT",
"Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT",
"Content-Type":"text/html"
},
"body":[
"no need."
]
},
"expected":{
"debug_log":"Failed to compile regular expression with macro \\(\\(\\):"
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS \"@rx ((%{TX.DOESNT_NEED_TO_EXIST_IT_WILL_BE_AN_EMPTY_STRING})\" \"id:1,phase:2,pass,t:trim\""
]
}
]

0 comments on commit 95f16ea

Please sign in to comment.