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