1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-16 02:50:07 +03:00

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.
This commit is contained in:
Nick Wellnhofer 2016-06-28 14:22:23 +02:00
parent a005199330
commit 9ab01a277d
4 changed files with 26 additions and 71 deletions

View File

@ -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

View File

@ -1,2 +1,3 @@
xpointer(id('chapter1')/p)
xpointer(id('chapter1')/p[1]/range-to(following-sibling::p[2]))
xpointer(range-to(id('chapter2')))

View File

@ -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,

View File

@ -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);
}
/**