[libxml2] Fix XPointer paths beginning with range-to



commit 9ab01a277d71f54d3143c2cf333c5c2e9aaedd9e
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Tue Jun 28 14:22:23 2016 +0200

    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(-)
---
diff --git a/result/XPath/xptr/vidbase b/result/XPath/xptr/vidbase
index 8b9e92d..f19193e 100644
--- a/result/XPath/xptr/vidbase
+++ b/result/XPath/xptr/vidbase
@@ -17,3 +17,16 @@ Object is a Location Set:
   To node
     ELEMENT p
 
+
+========================
+Expression: xpointer(range-to(id('chapter2')))
+Object is a Location Set:
+1 :   Object is a range :
+  From node
+     /
+  To node
+    ELEMENT chapter
+      ATTRIBUTE id
+        TEXT
+          content=chapter2
+
diff --git a/test/XPath/xptr/vidbase b/test/XPath/xptr/vidbase
index b146383..884b106 100644
--- a/test/XPath/xptr/vidbase
+++ b/test/XPath/xptr/vidbase
@@ -1,2 +1,3 @@
 xpointer(id('chapter1')/p)
 xpointer(id('chapter1')/p[1]/range-to(following-sibling::p[2]))
+xpointer(range-to(id('chapter2')))
diff --git a/xpath.c b/xpath.c
index d992841..5a01b1b 100644
--- a/xpath.c
+++ b/xpath.c
@@ -10691,13 +10691,18 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
                    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,
diff --git a/xpointer.c b/xpointer.c
index 676c510..d74174a 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -1332,8 +1332,6 @@ xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
     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(xmlXPathParserContextPtr ctxt, int nargs) {
  * @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);
 }
 
 /**


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