From 11ed4a7a90d5ce156a18980a4ad4e53e77384852 Mon Sep 17 00:00:00 2001 From: Pranjal Jumde Date: Wed, 2 Mar 2016 15:52:24 -0800 Subject: [PATCH] Heap use-after-free in htmlParsePubidLiteral and htmlParseSystemiteral For https://bugzilla.gnome.org/show_bug.cgi?id=760263 * HTMLparser.c: Add BASE_PTR convenience macro. (htmlParseSystemLiteral): Store length and start position instead of a pointer while iterating through the public identifier since the underlying buffer may change, resulting in a stale pointer being used. (htmlParsePubidLiteral): Ditto. Upstream-status: Backport CVE: CVE-2016-1837.patch Signed-off-by: Armin Kuster --- HTMLparser.c | 58 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 15 deletions(-) Index: libxml2-2.9.2/HTMLparser.c =================================================================== --- libxml2-2.9.2.orig/HTMLparser.c +++ libxml2-2.9.2/HTMLparser.c @@ -303,6 +303,7 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt) #define UPP(val) (toupper(ctxt->input->cur[(val)])) #define CUR_PTR ctxt->input->cur +#define BASE_PTR ctxt->input->base #define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ @@ -2773,31 +2774,43 @@ htmlParseAttValue(htmlParserCtxtPtr ctxt static xmlChar * htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) { - const xmlChar *q; + size_t len = 0, startPosition = 0; xmlChar *ret = NULL; if (CUR == '"') { NEXT; - q = CUR_PTR; - while ((IS_CHAR_CH(CUR)) && (CUR != '"')) + + if (CUR_PTR < BASE_PTR) + return(ret); + startPosition = CUR_PTR - BASE_PTR; + + while ((IS_CHAR_CH(CUR)) && (CUR != '"')) { NEXT; + len++; + } if (!IS_CHAR_CH(CUR)) { htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, "Unfinished SystemLiteral\n", NULL, NULL); } else { - ret = xmlStrndup(q, CUR_PTR - q); + ret = xmlStrndup((BASE_PTR+startPosition), len); NEXT; } } else if (CUR == '\'') { NEXT; - q = CUR_PTR; - while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) + + if (CUR_PTR < BASE_PTR) + return(ret); + startPosition = CUR_PTR - BASE_PTR; + + while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) { NEXT; + len++; + } if (!IS_CHAR_CH(CUR)) { htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, "Unfinished SystemLiteral\n", NULL, NULL); } else { - ret = xmlStrndup(q, CUR_PTR - q); + ret = xmlStrndup((BASE_PTR+startPosition), len); NEXT; } } else { @@ -2821,32 +2834,47 @@ htmlParseSystemLiteral(htmlParserCtxtPtr static xmlChar * htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) { - const xmlChar *q; + size_t len = 0, startPosition = 0; xmlChar *ret = NULL; /* * Name ::= (Letter | '_') (NameChar)* */ if (CUR == '"') { NEXT; - q = CUR_PTR; - while (IS_PUBIDCHAR_CH(CUR)) NEXT; + + if (CUR_PTR < BASE_PTR) + return(ret); + startPosition = CUR_PTR - BASE_PTR; + + while (IS_PUBIDCHAR_CH(CUR)) { + len++; + NEXT; + } + if (CUR != '"') { htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, "Unfinished PubidLiteral\n", NULL, NULL); } else { - ret = xmlStrndup(q, CUR_PTR - q); + ret = xmlStrndup((BASE_PTR + startPosition), len); NEXT; } } else if (CUR == '\'') { NEXT; - q = CUR_PTR; - while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')) - NEXT; + + if (CUR_PTR < BASE_PTR) + return(ret); + startPosition = CUR_PTR - BASE_PTR; + + while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')){ + len++; + NEXT; + } + if (CUR != '\'') { htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, "Unfinished PubidLiteral\n", NULL, NULL); } else { - ret = xmlStrndup(q, CUR_PTR - q); + ret = xmlStrndup((BASE_PTR + startPosition), len); NEXT; } } else {