From a820dbeac29d330bae4be05d9ecd939ad6b4aa33 Mon Sep 17 00:00:00 2001 From: Pranjal Jumde Date: Tue, 1 Mar 2016 11:34:04 -0800 Subject: [PATCH] Bug 758605: Heap-based buffer overread in xmlDictAddString Reviewed by David Kilzer. * HTMLparser.c: (htmlParseName): Add bounds check. (htmlParseNameComplex): Ditto. * result/HTML/758605.html: Added. * result/HTML/758605.html.err: Added. * result/HTML/758605.html.sax: Added. * runtest.c: (pushParseTest): The input for the new test case was so small (4 bytes) that htmlParseChunk() was never called after htmlCreatePushParserCtxt(), thereby creating a false positive test failure. Fixed by using a do-while loop so we always call htmlParseChunk() at least once. * test/HTML/758605.html: Added. Upstream-Status: Backport CVE: CVE-2016-1839 Signed-off-by: Armin Kuster --- HTMLparser.c | 8 ++++++++ result/HTML/758605.html | 3 +++ result/HTML/758605.html.err | 3 +++ result/HTML/758605.html.sax | 13 +++++++++++++ runtest.c | 4 ++-- test/HTML/758605.html | 1 + 6 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 result/HTML/758605.html create mode 100644 result/HTML/758605.html.err create mode 100644 result/HTML/758605.html.sax create mode 100644 test/HTML/758605.html Index: libxml2-2.9.2/HTMLparser.c =================================================================== --- libxml2-2.9.2.orig/HTMLparser.c +++ libxml2-2.9.2/HTMLparser.c @@ -2471,6 +2471,10 @@ htmlParseName(htmlParserCtxtPtr ctxt) { (*in == '_') || (*in == '-') || (*in == ':') || (*in == '.')) in++; + + if (in == ctxt->input->end) + return(NULL); + if ((*in > 0) && (*in < 0x80)) { count = in - ctxt->input->cur; ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count); @@ -2514,6 +2518,10 @@ htmlParseNameComplex(xmlParserCtxtPtr ct NEXTL(l); c = CUR_CHAR(l); } + + if (ctxt->input->base > ctxt->input->cur - len) + return(NULL); + return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); } Index: libxml2-2.9.2/result/HTML/758605.html =================================================================== --- /dev/null +++ libxml2-2.9.2/result/HTML/758605.html @@ -0,0 +1,3 @@ + +

& +

Index: libxml2-2.9.2/result/HTML/758605.html.err =================================================================== --- /dev/null +++ libxml2-2.9.2/result/HTML/758605.html.err @@ -0,0 +1,3 @@ +./test/HTML/758605.html:1: HTML parser error : htmlParseEntityRef: no name +ê + ^ Index: libxml2-2.9.2/result/HTML/758605.html.sax =================================================================== --- /dev/null +++ libxml2-2.9.2/result/HTML/758605.html.sax @@ -0,0 +1,13 @@ +SAX.setDocumentLocator() +SAX.startDocument() +SAX.error: htmlParseEntityRef: no name +SAX.startElement(html) +SAX.startElement(body) +SAX.startElement(p) +SAX.characters(&, 1) +SAX.ignorableWhitespace( +, 1) +SAX.endElement(p) +SAX.endElement(body) +SAX.endElement(html) +SAX.endDocument() Index: libxml2-2.9.2/runtest.c =================================================================== --- libxml2-2.9.2.orig/runtest.c +++ libxml2-2.9.2/runtest.c @@ -1827,7 +1827,7 @@ pushParseTest(const char *filename, cons ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename); xmlCtxtUseOptions(ctxt, options); cur += 4; - while (cur < size) { + do { if (cur + 1024 >= size) { #ifdef LIBXML_HTML_ENABLED if (options & XML_PARSE_HTML) @@ -1845,7 +1845,7 @@ pushParseTest(const char *filename, cons xmlParseChunk(ctxt, base + cur, 1024, 0); cur += 1024; } - } + } while (cur < size); doc = ctxt->myDoc; #ifdef LIBXML_HTML_ENABLED if (options & XML_PARSE_HTML) Index: libxml2-2.9.2/test/HTML/758605.html =================================================================== --- /dev/null +++ libxml2-2.9.2/test/HTML/758605.html @@ -0,0 +1 @@ +&:ê