1 From 9ab01a277d71f54d3143c2cf333c5c2e9aaedd9e Mon Sep 17 00:00:00 2001
2 From: Nick Wellnhofer <wellnhofer@aevum.de>
3 Date: Tue, 28 Jun 2016 14:22:23 +0200
4 Subject: [PATCH] Fix XPointer paths beginning with range-to
6 The old code would invoke the broken xmlXPtrRangeToFunction. range-to
7 isn't really a function but a special kind of location step. Remove
8 this function and always handle range-to in the XPath code.
10 The old xmlXPtrRangeToFunction could also be abused to trigger a
11 use-after-free error with the potential for remote code execution.
17 Signed-off-by: Baruch Siach <baruch@tkos.co.il>
19 Patch status: upstream commit 9ab01a277d7
21 result/XPath/xptr/vidbase | 13 ++++++++
22 test/XPath/xptr/vidbase | 1 +
24 xpointer.c | 76 ++++-------------------------------------------
25 4 files changed, 26 insertions(+), 71 deletions(-)
27 diff --git a/result/XPath/xptr/vidbase b/result/XPath/xptr/vidbase
28 index 8b9e92d66d97..f19193e70edb 100644
29 --- a/result/XPath/xptr/vidbase
30 +++ b/result/XPath/xptr/vidbase
31 @@ -17,3 +17,16 @@ Object is a Location Set:
36 +========================
37 +Expression: xpointer(range-to(id('chapter2')))
38 +Object is a Location Set:
39 +1 : Object is a range :
48 diff --git a/test/XPath/xptr/vidbase b/test/XPath/xptr/vidbase
49 index b1463830570a..884b1065d7fd 100644
50 --- a/test/XPath/xptr/vidbase
51 +++ b/test/XPath/xptr/vidbase
53 xpointer(id('chapter1')/p)
54 xpointer(id('chapter1')/p[1]/range-to(following-sibling::p[2]))
55 +xpointer(range-to(id('chapter2')))
56 diff --git a/xpath.c b/xpath.c
57 index d992841ef0c2..5a01b1b399a2 100644
60 @@ -10691,13 +10691,18 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
63 } else if ((NXT(len) == '(')) {
64 - /* Note Type or Function */
65 + /* Node Type or Function */
66 if (xmlXPathIsNodeType(name)) {
68 xmlGenericError(xmlGenericErrorContext,
69 "PathExpr: Type search\n");
72 +#ifdef LIBXML_XPTR_ENABLED
73 + } else if (ctxt->xptr &&
74 + xmlStrEqual(name, BAD_CAST "range-to")) {
79 xmlGenericError(xmlGenericErrorContext,
80 diff --git a/xpointer.c b/xpointer.c
81 index 676c5105837a..d74174a318f1 100644
84 @@ -1332,8 +1332,6 @@ xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
88 - xmlXPathRegisterFunc(ret, (xmlChar *)"range-to",
89 - xmlXPtrRangeToFunction);
90 xmlXPathRegisterFunc(ret, (xmlChar *)"range",
91 xmlXPtrRangeFunction);
92 xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside",
93 @@ -2243,76 +2241,14 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
94 * @nargs: the number of args
96 * Implement the range-to() XPointer function
98 + * Obsolete. range-to is not a real function but a special type of location
99 + * step which is handled in xpath.c.
102 -xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) {
103 - xmlXPathObjectPtr range;
104 - const xmlChar *cur;
105 - xmlXPathObjectPtr res, obj;
106 - xmlXPathObjectPtr tmp;
107 - xmlLocationSetPtr newset = NULL;
108 - xmlNodeSetPtr oldset;
111 - if (ctxt == NULL) return;
114 - * Save the expression pointer since we will have to evaluate
115 - * it multiple times. Initialize the new set.
117 - CHECK_TYPE(XPATH_NODESET);
118 - obj = valuePop(ctxt);
119 - oldset = obj->nodesetval;
120 - ctxt->context->node = NULL;
123 - newset = xmlXPtrLocationSetCreate(NULL);
125 - for (i = 0; i < oldset->nodeNr; i++) {
129 - * Run the evaluation with a node list made of a single item
132 - ctxt->context->node = oldset->nodeTab[i];
133 - tmp = xmlXPathNewNodeSet(ctxt->context->node);
134 - valuePush(ctxt, tmp);
136 - xmlXPathEvalExpr(ctxt);
140 - * The result of the evaluation need to be tested to
141 - * decided whether the filter succeeded or not
143 - res = valuePop(ctxt);
144 - range = xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], res);
145 - if (range != NULL) {
146 - xmlXPtrLocationSetAdd(newset, range);
153 - xmlXPathFreeObject(res);
154 - if (ctxt->value == tmp) {
155 - res = valuePop(ctxt);
156 - xmlXPathFreeObject(res);
159 - ctxt->context->node = NULL;
163 - * The result is used as the new evaluation set.
165 - xmlXPathFreeObject(obj);
166 - ctxt->context->node = NULL;
167 - ctxt->context->contextSize = -1;
168 - ctxt->context->proximityPosition = -1;
169 - valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
170 +xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
171 + int nargs ATTRIBUTE_UNUSED) {
172 + XP_ERROR(XPATH_EXPR_ERROR);