123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- From 9ab01a277d71f54d3143c2cf333c5c2e9aaedd9e Mon Sep 17 00:00:00 2001
- From: Nick Wellnhofer <wellnhofer@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.
- Signed-off-by: Baruch Siach <baruch@tkos.co.il>
- ---
- Patch status: upstream commit 9ab01a277d7
- 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 8b9e92d66d97..f19193e70edb 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 b1463830570a..884b1065d7fd 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 d992841ef0c2..5a01b1b399a2 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 676c5105837a..d74174a318f1 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);
- }
-
- /**
- --
- 2.10.2
|