Control: tags 840553 + pending
Control: tags 840554 + pending

Dear maintainer,

I've prepared an NMU for libxml2 (versioned as 2.9.4+dfsg1-2.1) and
uploaded it to DELAYED/5. Please feel free to tell me if I
should delay it longer.

Regards,
Salvatore
diff -Nru libxml2-2.9.4+dfsg1/debian/changelog libxml2-2.9.4+dfsg1/debian/changelog
--- libxml2-2.9.4+dfsg1/debian/changelog	2016-09-11 20:57:02.000000000 +0200
+++ libxml2-2.9.4+dfsg1/debian/changelog	2016-10-30 16:30:55.000000000 +0100
@@ -1,3 +1,15 @@
+libxml2 (2.9.4+dfsg1-2.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Fix comparison with root node in xmlXPathCmpNodes
+  * Fix XPointer paths beginning with range-to (CVE-2016-5131)
+    (Closes: #840554)
+  * Disallow namespace nodes in XPointer ranges (CVE-2016-4658)
+    (Closes: #840553)
+  * Fix more NULL pointer derefs in xpointer.c
+
+ -- Salvatore Bonaccorso <car...@debian.org>  Sun, 30 Oct 2016 16:30:55 +0100
+
 libxml2 (2.9.4+dfsg1-2) unstable; urgency=medium
 
   [ YunQiang Su ]
diff -Nru libxml2-2.9.4+dfsg1/debian/patches/0004-Fix-comparison-with-root-node-in-xmlXPathCmpNodes.patch libxml2-2.9.4+dfsg1/debian/patches/0004-Fix-comparison-with-root-node-in-xmlXPathCmpNodes.patch
--- libxml2-2.9.4+dfsg1/debian/patches/0004-Fix-comparison-with-root-node-in-xmlXPathCmpNodes.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.4+dfsg1/debian/patches/0004-Fix-comparison-with-root-node-in-xmlXPathCmpNodes.patch	2016-10-30 16:30:55.000000000 +0100
@@ -0,0 +1,34 @@
+From a005199330b86dada19d162cae15ef9bdcb6baa8 Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnho...@aevum.de>
+Date: Tue, 28 Jun 2016 14:19:58 +0200
+Subject: [PATCH] Fix comparison with root node in xmlXPathCmpNodes
+
+This change has already been made in xmlXPathCmpNodesExt but not in
+xmlXPathCmpNodes.
+---
+ xpath.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/xpath.c b/xpath.c
+index 751665b..d992841 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -3342,13 +3342,13 @@ xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
+      * compute depth to root
+      */
+     for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
+-	if (cur == node1)
++	if (cur->parent == node1)
+ 	    return(1);
+ 	depth2++;
+     }
+     root = cur;
+     for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
+-	if (cur == node2)
++	if (cur->parent == node2)
+ 	    return(-1);
+ 	depth1++;
+     }
+-- 
+2.10.1
+
diff -Nru libxml2-2.9.4+dfsg1/debian/patches/0005-Fix-XPointer-paths-beginning-with-range-to.patch libxml2-2.9.4+dfsg1/debian/patches/0005-Fix-XPointer-paths-beginning-with-range-to.patch
--- libxml2-2.9.4+dfsg1/debian/patches/0005-Fix-XPointer-paths-beginning-with-range-to.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.4+dfsg1/debian/patches/0005-Fix-XPointer-paths-beginning-with-range-to.patch	2016-10-30 16:30:55.000000000 +0100
@@ -0,0 +1,138 @@
+From 9ab01a277d71f54d3143c2cf333c5c2e9aaedd9e Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnho...@aevum.de>
+Date: Tue, 28 Jun 2016 14:22:23 +0200
+Subject: [PATCH] Fix XPointer paths beginning with range-to
+
+The old code would invoke the broken xmlXPtrRangeToFunction. range-to
+isn't really a function but a special kind of location step. Remove
+this function and always handle range-to in the XPath code.
+
+The old xmlXPtrRangeToFunction could also be abused to trigger a
+use-after-free error with the potential for remote code execution.
+
+Found with afl-fuzz.
+
+Fixes CVE-2016-5131.
+---
+ result/XPath/xptr/vidbase | 13 ++++++++
+ test/XPath/xptr/vidbase   |  1 +
+ xpath.c                   |  7 ++++-
+ xpointer.c                | 76 ++++-------------------------------------------
+ 4 files changed, 26 insertions(+), 71 deletions(-)
+
+--- a/xpath.c
++++ b/xpath.c
+@@ -10691,13 +10691,18 @@ xmlXPathCompPathExpr(xmlXPathParserConte
+ 		    lc = 1;
+ 		    break;
+ 		} else if ((NXT(len) == '(')) {
+-		    /* Note Type or Function */
++		    /* Node Type or Function */
+ 		    if (xmlXPathIsNodeType(name)) {
+ #ifdef DEBUG_STEP
+ 		        xmlGenericError(xmlGenericErrorContext,
+ 				"PathExpr: Type search\n");
+ #endif
+ 			lc = 1;
++#ifdef LIBXML_XPTR_ENABLED
++                    } else if (ctxt->xptr &&
++                               xmlStrEqual(name, BAD_CAST "range-to")) {
++                        lc = 1;
++#endif
+ 		    } else {
+ #ifdef DEBUG_STEP
+ 		        xmlGenericError(xmlGenericErrorContext,
+--- a/xpointer.c
++++ b/xpointer.c
+@@ -1332,8 +1332,6 @@ xmlXPtrNewContext(xmlDocPtr doc, xmlNode
+     ret->here = here;
+     ret->origin = origin;
+ 
+-    xmlXPathRegisterFunc(ret, (xmlChar *)"range-to",
+-	                 xmlXPtrRangeToFunction);
+     xmlXPathRegisterFunc(ret, (xmlChar *)"range",
+ 	                 xmlXPtrRangeFunction);
+     xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside",
+@@ -2243,76 +2241,14 @@ xmlXPtrRangeInsideFunction(xmlXPathParse
+  * @nargs:  the number of args
+  *
+  * Implement the range-to() XPointer function
++ *
++ * Obsolete. range-to is not a real function but a special type of location
++ * step which is handled in xpath.c.
+  */
+ void
+-xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+-    xmlXPathObjectPtr range;
+-    const xmlChar *cur;
+-    xmlXPathObjectPtr res, obj;
+-    xmlXPathObjectPtr tmp;
+-    xmlLocationSetPtr newset = NULL;
+-    xmlNodeSetPtr oldset;
+-    int i;
+-
+-    if (ctxt == NULL) return;
+-    CHECK_ARITY(1);
+-    /*
+-     * Save the expression pointer since we will have to evaluate
+-     * it multiple times. Initialize the new set.
+-     */
+-    CHECK_TYPE(XPATH_NODESET);
+-    obj = valuePop(ctxt);
+-    oldset = obj->nodesetval;
+-    ctxt->context->node = NULL;
+-
+-    cur = ctxt->cur;
+-    newset = xmlXPtrLocationSetCreate(NULL);
+-
+-    for (i = 0; i < oldset->nodeNr; i++) {
+-	ctxt->cur = cur;
+-
+-	/*
+-	 * Run the evaluation with a node list made of a single item
+-	 * in the nodeset.
+-	 */
+-	ctxt->context->node = oldset->nodeTab[i];
+-	tmp = xmlXPathNewNodeSet(ctxt->context->node);
+-	valuePush(ctxt, tmp);
+-
+-	xmlXPathEvalExpr(ctxt);
+-	CHECK_ERROR;
+-
+-	/*
+-	 * The result of the evaluation need to be tested to
+-	 * decided whether the filter succeeded or not
+-	 */
+-	res = valuePop(ctxt);
+-	range = xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], res);
+-	if (range != NULL) {
+-	    xmlXPtrLocationSetAdd(newset, range);
+-	}
+-
+-	/*
+-	 * Cleanup
+-	 */
+-	if (res != NULL)
+-	    xmlXPathFreeObject(res);
+-	if (ctxt->value == tmp) {
+-	    res = valuePop(ctxt);
+-	    xmlXPathFreeObject(res);
+-	}
+-
+-	ctxt->context->node = NULL;
+-    }
+-
+-    /*
+-     * The result is used as the new evaluation set.
+-     */
+-    xmlXPathFreeObject(obj);
+-    ctxt->context->node = NULL;
+-    ctxt->context->contextSize = -1;
+-    ctxt->context->proximityPosition = -1;
+-    valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
++xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
++                       int nargs ATTRIBUTE_UNUSED) {
++    XP_ERROR(XPATH_EXPR_ERROR);
+ }
+ 
+ /**
diff -Nru libxml2-2.9.4+dfsg1/debian/patches/0006-Disallow-namespace-nodes-in-XPointer-ranges.patch libxml2-2.9.4+dfsg1/debian/patches/0006-Disallow-namespace-nodes-in-XPointer-ranges.patch
--- libxml2-2.9.4+dfsg1/debian/patches/0006-Disallow-namespace-nodes-in-XPointer-ranges.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.4+dfsg1/debian/patches/0006-Disallow-namespace-nodes-in-XPointer-ranges.patch	2016-10-30 16:30:55.000000000 +0100
@@ -0,0 +1,249 @@
+From c1d1f7121194036608bf555f08d3062a36fd344b Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnho...@aevum.de>
+Date: Tue, 28 Jun 2016 18:34:52 +0200
+Subject: [PATCH] Disallow namespace nodes in XPointer ranges
+
+Namespace nodes must be copied to avoid use-after-free errors.
+But they don't necessarily have a physical representation in a
+document, so simply disallow them in XPointer ranges.
+
+Found with afl-fuzz.
+
+Fixes CVE-2016-4658.
+---
+ xpointer.c | 149 +++++++++++++++++++++++--------------------------------------
+ 1 file changed, 56 insertions(+), 93 deletions(-)
+
+diff --git a/xpointer.c b/xpointer.c
+index a7b03fb..694d120 100644
+--- a/xpointer.c
++++ b/xpointer.c
+@@ -320,6 +320,45 @@ xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
+ }
+ 
+ /**
++ * xmlXPtrNewRangeInternal:
++ * @start:  the starting node
++ * @startindex:  the start index
++ * @end:  the ending point
++ * @endindex:  the ending index
++ *
++ * Internal function to create a new xmlXPathObjectPtr of type range
++ *
++ * Returns the newly created object.
++ */
++static xmlXPathObjectPtr
++xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
++                        xmlNodePtr end, int endindex) {
++    xmlXPathObjectPtr ret;
++
++    /*
++     * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
++     * Disallow them for now.
++     */
++    if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
++	return(NULL);
++    if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
++	return(NULL);
++
++    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
++    if (ret == NULL) {
++        xmlXPtrErrMemory("allocating range");
++	return(NULL);
++    }
++    memset(ret, 0, sizeof(xmlXPathObject));
++    ret->type = XPATH_RANGE;
++    ret->user = start;
++    ret->index = startindex;
++    ret->user2 = end;
++    ret->index2 = endindex;
++    return(ret);
++}
++
++/**
+  * xmlXPtrNewRange:
+  * @start:  the starting node
+  * @startindex:  the start index
+@@ -344,17 +383,7 @@ xmlXPtrNewRange(xmlNodePtr start, int startindex,
+     if (endindex < 0)
+ 	return(NULL);
+ 
+-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+-    if (ret == NULL) {
+-        xmlXPtrErrMemory("allocating range");
+-	return(NULL);
+-    }
+-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+-    ret->type = XPATH_RANGE;
+-    ret->user = start;
+-    ret->index = startindex;
+-    ret->user2 = end;
+-    ret->index2 = endindex;
++    ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
+     xmlXPtrRangeCheckOrder(ret);
+     return(ret);
+ }
+@@ -381,17 +410,8 @@ xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
+     if (end->type != XPATH_POINT)
+ 	return(NULL);
+ 
+-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+-    if (ret == NULL) {
+-        xmlXPtrErrMemory("allocating range");
+-	return(NULL);
+-    }
+-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+-    ret->type = XPATH_RANGE;
+-    ret->user = start->user;
+-    ret->index = start->index;
+-    ret->user2 = end->user;
+-    ret->index2 = end->index;
++    ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
++                                  end->index);
+     xmlXPtrRangeCheckOrder(ret);
+     return(ret);
+ }
+@@ -416,17 +436,7 @@ xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
+     if (start->type != XPATH_POINT)
+ 	return(NULL);
+ 
+-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+-    if (ret == NULL) {
+-        xmlXPtrErrMemory("allocating range");
+-	return(NULL);
+-    }
+-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+-    ret->type = XPATH_RANGE;
+-    ret->user = start->user;
+-    ret->index = start->index;
+-    ret->user2 = end;
+-    ret->index2 = -1;
++    ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
+     xmlXPtrRangeCheckOrder(ret);
+     return(ret);
+ }
+@@ -453,17 +463,7 @@ xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
+     if (end->type != XPATH_POINT)
+ 	return(NULL);
+ 
+-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+-    if (ret == NULL) {
+-        xmlXPtrErrMemory("allocating range");
+-	return(NULL);
+-    }
+-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+-    ret->type = XPATH_RANGE;
+-    ret->user = start;
+-    ret->index = -1;
+-    ret->user2 = end->user;
+-    ret->index2 = end->index;
++    ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
+     xmlXPtrRangeCheckOrder(ret);
+     return(ret);
+ }
+@@ -486,17 +486,7 @@ xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
+     if (end == NULL)
+ 	return(NULL);
+ 
+-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+-    if (ret == NULL) {
+-        xmlXPtrErrMemory("allocating range");
+-	return(NULL);
+-    }
+-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+-    ret->type = XPATH_RANGE;
+-    ret->user = start;
+-    ret->index = -1;
+-    ret->user2 = end;
+-    ret->index2 = -1;
++    ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
+     xmlXPtrRangeCheckOrder(ret);
+     return(ret);
+ }
+@@ -516,17 +506,7 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
+     if (start == NULL)
+ 	return(NULL);
+ 
+-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+-    if (ret == NULL) {
+-        xmlXPtrErrMemory("allocating range");
+-	return(NULL);
+-    }
+-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+-    ret->type = XPATH_RANGE;
+-    ret->user = start;
+-    ret->index = -1;
+-    ret->user2 = NULL;
+-    ret->index2 = -1;
++    ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
+     return(ret);
+ }
+ 
+@@ -541,6 +521,8 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
+  */
+ xmlXPathObjectPtr
+ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
++    xmlNodePtr endNode;
++    int endIndex;
+     xmlXPathObjectPtr ret;
+ 
+     if (start == NULL)
+@@ -549,7 +531,12 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
+ 	return(NULL);
+     switch (end->type) {
+ 	case XPATH_POINT:
++	    endNode = end->user;
++	    endIndex = end->index;
++	    break;
+ 	case XPATH_RANGE:
++	    endNode = end->user2;
++	    endIndex = end->index2;
+ 	    break;
+ 	case XPATH_NODESET:
+ 	    /*
+@@ -557,39 +544,15 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
+ 	     */
+ 	    if (end->nodesetval->nodeNr <= 0)
+ 		return(NULL);
++	    endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
++	    endIndex = -1;
+ 	    break;
+ 	default:
+ 	    /* TODO */
+ 	    return(NULL);
+     }
+ 
+-    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+-    if (ret == NULL) {
+-        xmlXPtrErrMemory("allocating range");
+-	return(NULL);
+-    }
+-    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+-    ret->type = XPATH_RANGE;
+-    ret->user = start;
+-    ret->index = -1;
+-    switch (end->type) {
+-	case XPATH_POINT:
+-	    ret->user2 = end->user;
+-	    ret->index2 = end->index;
+-	    break;
+-	case XPATH_RANGE:
+-	    ret->user2 = end->user2;
+-	    ret->index2 = end->index2;
+-	    break;
+-	case XPATH_NODESET: {
+-	    ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
+-	    ret->index2 = -1;
+-	    break;
+-	}
+-	default:
+-	    STRANGE
+-	    return(NULL);
+-    }
++    ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
+     xmlXPtrRangeCheckOrder(ret);
+     return(ret);
+ }
+-- 
+2.10.1
+
diff -Nru libxml2-2.9.4+dfsg1/debian/patches/0007-Fix-more-NULL-pointer-derefs-in-xpointer.c.patch libxml2-2.9.4+dfsg1/debian/patches/0007-Fix-more-NULL-pointer-derefs-in-xpointer.c.patch
--- libxml2-2.9.4+dfsg1/debian/patches/0007-Fix-more-NULL-pointer-derefs-in-xpointer.c.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.4+dfsg1/debian/patches/0007-Fix-more-NULL-pointer-derefs-in-xpointer.c.patch	2016-10-30 16:30:55.000000000 +0100
@@ -0,0 +1,50 @@
+From e905f08123e4a6e7731549e6f09dadff4cab65bd Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnho...@aevum.de>
+Date: Sun, 26 Jun 2016 12:38:28 +0200
+Subject: [PATCH] Fix more NULL pointer derefs in xpointer.c
+
+Found with afl-fuzz.
+---
+ xpointer.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/xpointer.c b/xpointer.c
+index 694d120..e643ee9 100644
+--- a/xpointer.c
++++ b/xpointer.c
+@@ -542,7 +542,7 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
+ 	    /*
+ 	     * Empty set ...
+ 	     */
+-	    if (end->nodesetval->nodeNr <= 0)
++	    if ((end->nodesetval == NULL) || (end->nodesetval->nodeNr <= 0))
+ 		return(NULL);
+ 	    endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
+ 	    endIndex = -1;
+@@ -1361,7 +1361,7 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
+ 		     */
+ 		    xmlNodeSetPtr set;
+ 		    set = tmp->nodesetval;
+-		    if ((set->nodeNr != 1) ||
++		    if ((set == NULL) || (set->nodeNr != 1) ||
+ 			(set->nodeTab[0] != (xmlNodePtr) ctx->doc))
+ 			stack++;
+ 		} else
+@@ -2034,9 +2034,11 @@ xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ 	xmlXPathFreeObject(set);
+         XP_ERROR(XPATH_MEMORY_ERROR);
+     }
+-    for (i = 0;i < oldset->locNr;i++) {
+-	xmlXPtrLocationSetAdd(newset,
+-		xmlXPtrCoveringRange(ctxt, oldset->locTab[i]));
++    if (oldset != NULL) {
++        for (i = 0;i < oldset->locNr;i++) {
++            xmlXPtrLocationSetAdd(newset,
++                    xmlXPtrCoveringRange(ctxt, oldset->locTab[i]));
++        }
+     }
+ 
+     /*
+-- 
+2.1.4
+
diff -Nru libxml2-2.9.4+dfsg1/debian/patches/series libxml2-2.9.4+dfsg1/debian/patches/series
--- libxml2-2.9.4+dfsg1/debian/patches/series	2016-07-19 05:41:32.000000000 +0200
+++ libxml2-2.9.4+dfsg1/debian/patches/series	2016-10-30 16:30:55.000000000 +0100
@@ -1,3 +1,7 @@
 0001-modify-xml2-config-and-pkgconfig-behaviour.patch
 0002-fix-python-multiarch-includes.patch
 0003-Fix-NULL-pointer-deref-in-XPointer-range-to.patch
+0004-Fix-comparison-with-root-node-in-xmlXPathCmpNodes.patch
+0005-Fix-XPointer-paths-beginning-with-range-to.patch
+0006-Disallow-namespace-nodes-in-XPointer-ranges.patch
+0007-Fix-more-NULL-pointer-derefs-in-xpointer.c.patch

Reply via email to