7219eb
From c1d1f7121194036608bf555f08d3062a36fd344b Mon Sep 17 00:00:00 2001
7219eb
From: Nick Wellnhofer <wellnhofer@aevum.de>
7219eb
Date: Tue, 28 Jun 2016 18:34:52 +0200
7219eb
Subject: [PATCH] Disallow namespace nodes in XPointer ranges
7219eb
7219eb
Namespace nodes must be copied to avoid use-after-free errors.
7219eb
But they don't necessarily have a physical representation in a
7219eb
document, so simply disallow them in XPointer ranges.
7219eb
7219eb
Found with afl-fuzz.
7219eb
7219eb
Fixes CVE-2016-4658.
7219eb
---
7219eb
 xpointer.c | 149 ++++++++++++++++++++---------------------------------
7219eb
 1 file changed, 56 insertions(+), 93 deletions(-)
7219eb
7219eb
diff --git a/xpointer.c b/xpointer.c
7219eb
index a7b03fbd..694d120e 100644
7219eb
--- a/xpointer.c
7219eb
+++ b/xpointer.c
7219eb
@@ -319,6 +319,45 @@ xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
7219eb
     return(1);
7219eb
 }
7219eb
 
7219eb
+/**
7219eb
+ * xmlXPtrNewRangeInternal:
7219eb
+ * @start:  the starting node
7219eb
+ * @startindex:  the start index
7219eb
+ * @end:  the ending point
7219eb
+ * @endindex:  the ending index
7219eb
+ *
7219eb
+ * Internal function to create a new xmlXPathObjectPtr of type range
7219eb
+ *
7219eb
+ * Returns the newly created object.
7219eb
+ */
7219eb
+static xmlXPathObjectPtr
7219eb
+xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
7219eb
+                        xmlNodePtr end, int endindex) {
7219eb
+    xmlXPathObjectPtr ret;
7219eb
+
7219eb
+    /*
7219eb
+     * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
7219eb
+     * Disallow them for now.
7219eb
+     */
7219eb
+    if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
7219eb
+	return(NULL);
7219eb
+    if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
7219eb
+	return(NULL);
7219eb
+
7219eb
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
+    if (ret == NULL) {
7219eb
+        xmlXPtrErrMemory("allocating range");
7219eb
+	return(NULL);
7219eb
+    }
7219eb
+    memset(ret, 0, sizeof(xmlXPathObject));
7219eb
+    ret->type = XPATH_RANGE;
7219eb
+    ret->user = start;
7219eb
+    ret->index = startindex;
7219eb
+    ret->user2 = end;
7219eb
+    ret->index2 = endindex;
7219eb
+    return(ret);
7219eb
+}
7219eb
+
7219eb
 /**
7219eb
  * xmlXPtrNewRange:
7219eb
  * @start:  the starting node
7219eb
@@ -344,17 +383,7 @@ xmlXPtrNewRange(xmlNodePtr start, int startindex,
7219eb
     if (endindex < 0)
7219eb
 	return(NULL);
7219eb
 
7219eb
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
-    if (ret == NULL) {
7219eb
-        xmlXPtrErrMemory("allocating range");
7219eb
-	return(NULL);
7219eb
-    }
7219eb
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
7219eb
-    ret->type = XPATH_RANGE;
7219eb
-    ret->user = start;
7219eb
-    ret->index = startindex;
7219eb
-    ret->user2 = end;
7219eb
-    ret->index2 = endindex;
7219eb
+    ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
7219eb
     xmlXPtrRangeCheckOrder(ret);
7219eb
     return(ret);
7219eb
 }
7219eb
@@ -381,17 +410,8 @@ xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
7219eb
     if (end->type != XPATH_POINT)
7219eb
 	return(NULL);
7219eb
 
7219eb
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
-    if (ret == NULL) {
7219eb
-        xmlXPtrErrMemory("allocating range");
7219eb
-	return(NULL);
7219eb
-    }
7219eb
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
7219eb
-    ret->type = XPATH_RANGE;
7219eb
-    ret->user = start->user;
7219eb
-    ret->index = start->index;
7219eb
-    ret->user2 = end->user;
7219eb
-    ret->index2 = end->index;
7219eb
+    ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
7219eb
+                                  end->index);
7219eb
     xmlXPtrRangeCheckOrder(ret);
7219eb
     return(ret);
7219eb
 }
7219eb
@@ -416,17 +436,7 @@ xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
7219eb
     if (start->type != XPATH_POINT)
7219eb
 	return(NULL);
7219eb
 
7219eb
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
-    if (ret == NULL) {
7219eb
-        xmlXPtrErrMemory("allocating range");
7219eb
-	return(NULL);
7219eb
-    }
7219eb
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
7219eb
-    ret->type = XPATH_RANGE;
7219eb
-    ret->user = start->user;
7219eb
-    ret->index = start->index;
7219eb
-    ret->user2 = end;
7219eb
-    ret->index2 = -1;
7219eb
+    ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
7219eb
     xmlXPtrRangeCheckOrder(ret);
7219eb
     return(ret);
7219eb
 }
7219eb
@@ -453,17 +463,7 @@ xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
7219eb
     if (end->type != XPATH_POINT)
7219eb
 	return(NULL);
7219eb
 
7219eb
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
-    if (ret == NULL) {
7219eb
-        xmlXPtrErrMemory("allocating range");
7219eb
-	return(NULL);
7219eb
-    }
7219eb
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
7219eb
-    ret->type = XPATH_RANGE;
7219eb
-    ret->user = start;
7219eb
-    ret->index = -1;
7219eb
-    ret->user2 = end->user;
7219eb
-    ret->index2 = end->index;
7219eb
+    ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
7219eb
     xmlXPtrRangeCheckOrder(ret);
7219eb
     return(ret);
7219eb
 }
7219eb
@@ -486,17 +486,7 @@ xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
7219eb
     if (end == NULL)
7219eb
 	return(NULL);
7219eb
 
7219eb
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
-    if (ret == NULL) {
7219eb
-        xmlXPtrErrMemory("allocating range");
7219eb
-	return(NULL);
7219eb
-    }
7219eb
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
7219eb
-    ret->type = XPATH_RANGE;
7219eb
-    ret->user = start;
7219eb
-    ret->index = -1;
7219eb
-    ret->user2 = end;
7219eb
-    ret->index2 = -1;
7219eb
+    ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
7219eb
     xmlXPtrRangeCheckOrder(ret);
7219eb
     return(ret);
7219eb
 }
7219eb
@@ -516,17 +506,7 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
7219eb
     if (start == NULL)
7219eb
 	return(NULL);
7219eb
 
7219eb
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
-    if (ret == NULL) {
7219eb
-        xmlXPtrErrMemory("allocating range");
7219eb
-	return(NULL);
7219eb
-    }
7219eb
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
7219eb
-    ret->type = XPATH_RANGE;
7219eb
-    ret->user = start;
7219eb
-    ret->index = -1;
7219eb
-    ret->user2 = NULL;
7219eb
-    ret->index2 = -1;
7219eb
+    ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
7219eb
     return(ret);
7219eb
 }
7219eb
 
7219eb
@@ -541,6 +521,8 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
7219eb
  */
7219eb
 xmlXPathObjectPtr
7219eb
 xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
7219eb
+    xmlNodePtr endNode;
7219eb
+    int endIndex;
7219eb
     xmlXPathObjectPtr ret;
7219eb
 
7219eb
     if (start == NULL)
7219eb
@@ -549,7 +531,12 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
7219eb
 	return(NULL);
7219eb
     switch (end->type) {
7219eb
 	case XPATH_POINT:
7219eb
+	    endNode = end->user;
7219eb
+	    endIndex = end->index;
7219eb
+	    break;
7219eb
 	case XPATH_RANGE:
7219eb
+	    endNode = end->user2;
7219eb
+	    endIndex = end->index2;
7219eb
 	    break;
7219eb
 	case XPATH_NODESET:
7219eb
 	    /*
7219eb
@@ -557,39 +544,15 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
7219eb
 	     */
7219eb
 	    if (end->nodesetval->nodeNr <= 0)
7219eb
 		return(NULL);
7219eb
+	    endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
7219eb
+	    endIndex = -1;
7219eb
 	    break;
7219eb
 	default:
7219eb
 	    /* TODO */
7219eb
 	    return(NULL);
7219eb
     }
7219eb
 
7219eb
-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
7219eb
-    if (ret == NULL) {
7219eb
-        xmlXPtrErrMemory("allocating range");
7219eb
-	return(NULL);
7219eb
-    }
7219eb
-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
7219eb
-    ret->type = XPATH_RANGE;
7219eb
-    ret->user = start;
7219eb
-    ret->index = -1;
7219eb
-    switch (end->type) {
7219eb
-	case XPATH_POINT:
7219eb
-	    ret->user2 = end->user;
7219eb
-	    ret->index2 = end->index;
7219eb
-	    break;
7219eb
-	case XPATH_RANGE:
7219eb
-	    ret->user2 = end->user2;
7219eb
-	    ret->index2 = end->index2;
7219eb
-	    break;
7219eb
-	case XPATH_NODESET: {
7219eb
-	    ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
7219eb
-	    ret->index2 = -1;
7219eb
-	    break;
7219eb
-	}
7219eb
-	default:
7219eb
-	    STRANGE
7219eb
-	    return(NULL);
7219eb
-    }
7219eb
+    ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
7219eb
     xmlXPtrRangeCheckOrder(ret);
7219eb
     return(ret);
7219eb
 }
7219eb
-- 
7219eb
GitLab
7219eb