diff --git a/src/request_body_processor/xml.cc b/src/request_body_processor/xml.cc
index cbb7894c9..4fe67a7eb 100644
--- a/src/request_body_processor/xml.cc
+++ b/src/request_body_processor/xml.cc
@@ -165,12 +165,21 @@ XML::~XML() {
xmlFreeParserCtxt(m_data.parsing_ctx);
m_data.parsing_ctx = NULL;
}
+ freeArgsParserCtx();
if (m_data.doc != NULL) {
xmlFreeDoc(m_data.doc);
m_data.doc = NULL;
}
}
+
+void XML::freeArgsParserCtx() {
+ if (m_data.parsing_ctx_arg != nullptr) {
+ xmlFreeParserCtxt(m_data.parsing_ctx_arg);
+ m_data.parsing_ctx_arg = nullptr;
+ }
+}
+
bool XML::init() {
//xmlParserInputBufferCreateFilenameFunc entity;
if (m_transaction->m_rules->m_secXMLExternalEntity
@@ -329,6 +338,7 @@ bool XML::complete(std::string *error) {
if (m_data.well_formed != 1) {
error->assign("XML: Failed to parse document.");
ms_dbg_a(m_transaction, 4, "XML: Failed to parse document.");
+ freeArgsParserCtx();
return false;
}
}
diff --git a/src/request_body_processor/xml.h b/src/request_body_processor/xml.h
index aac1299de..9a7359525 100644
--- a/src/request_body_processor/xml.h
+++ b/src/request_body_processor/xml.h
@@ -96,6 +96,7 @@ class XML {
xml_data m_data;
private:
+ void freeArgsParserCtx();
Transaction *m_transaction;
std::string m_header;
};
diff --git a/test/test-cases/regression/request-body-parser-xml-into-args.json b/test/test-cases/regression/request-body-parser-xml-into-args.json
new file mode 100644
index 000000000..ea542b2eb
--- /dev/null
+++ b/test/test-cases/regression/request-body-parser-xml-into-args.json
@@ -0,0 +1,96 @@
+[
+ {
+ "enabled": 1,
+ "version_min": 300000,
+ "title": "XML request body parser with SecParseXmlIntoArgs (mismatched end tag)",
+ "resource": "libxml2",
+ "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-Type": "text/xml",
+ "Content-Length": "10"
+ },
+ "uri": "/",
+ "method": "POST",
+ "body": [
+ ""
+ ]
+ },
+ "response": {
+ "headers": {
+ "Content-Length": "0"
+ },
+ "body": [
+ ""
+ ]
+ },
+ "expected": {
+ "debug_log": "XML: Failed to parse document",
+ "http_code": 200
+ },
+ "rules": [
+ "SecRuleEngine On",
+ "SecRequestBodyAccess On",
+ "SecParseXmlIntoArgs On",
+ "SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500080,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
+ "SecRule REQBODY_ERROR \"!@eq 0\" \"id:500081,phase:2,pass,log\""
+ ]
+ },
+ {
+ "enabled": 1,
+ "version_min": 300000,
+ "title": "XML request body parser with SecParseXmlIntoArgs (truncated document)",
+ "resource": "libxml2",
+ "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-Type": "text/xml",
+ "Content-Length": "6"
+ },
+ "uri": "/",
+ "method": "POST",
+ "body": [
+ ""
+ ]
+ },
+ "response": {
+ "headers": {
+ "Content-Length": "0"
+ },
+ "body": [
+ ""
+ ]
+ },
+ "expected": {
+ "debug_log": "XML: Failed to parse document",
+ "http_code": 200
+ },
+ "rules": [
+ "SecRuleEngine On",
+ "SecRequestBodyAccess On",
+ "SecParseXmlIntoArgs On",
+ "SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500080,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
+ "SecRule REQBODY_ERROR \"!@eq 0\" \"id:500081,phase:2,pass,log\""
+ ]
+ }
+]
diff --git a/test/test-suite.in b/test/test-suite.in
index ebda49fb8..1ee362ab9 100644
--- a/test/test-suite.in
+++ b/test/test-suite.in
@@ -99,6 +99,7 @@ TESTS+=test/test-cases/regression/request-body-parser-json.json
TESTS+=test/test-cases/regression/request-body-parser-multipart-crlf.json
TESTS+=test/test-cases/regression/request-body-parser-multipart.json
TESTS+=test/test-cases/regression/request-body-parser-xml.json
+TESTS+=test/test-cases/regression/request-body-parser-xml-into-args.json
TESTS+=test/test-cases/regression/request-body-parser-xml-validade-dtd.json
TESTS+=test/test-cases/regression/rule-920120.json
TESTS+=test/test-cases/regression/rule-920200.json