[libxml2] Heap use-after-free in htmlParsePubidLiteral and htmlParseSystemiteral



commit 11ed4a7a90d5ce156a18980a4ad4e53e77384852
Author: Pranjal Jumde <pjumde apple com>
Date:   Wed Mar 2 15:52:24 2016 -0800

    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.

 HTMLparser.c |   58 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 43 insertions(+), 15 deletions(-)
---
diff --git a/HTMLparser.c b/HTMLparser.c
index 0985d1d..d1395fa 100644
--- a/HTMLparser.c
+++ b/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)) \
@@ -2781,31 +2782,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 {
@@ -2829,32 +2842,47 @@ htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
 
 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 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]