http://git.gnome.org/browse/libxml2/commit/?id=f5048b3e71fc30ad096970b8df6e7af073bae4cb diff -Naurp libxml2-2.7.8/include/libxml/xpath.h libxml2-2.7.8.oden/include/libxml/xpath.h --- libxml2-2.7.8/include/libxml/xpath.h 2010-10-12 06:25:32.000000000 +0000 +++ libxml2-2.7.8.oden/include/libxml/xpath.h 2011-10-09 13:01:09.000000000 +0000 @@ -68,7 +68,8 @@ typedef enum { XPATH_UNDEF_PREFIX_ERROR, XPATH_ENCODING_ERROR, XPATH_INVALID_CHAR_ERROR, - XPATH_INVALID_CTXT + XPATH_INVALID_CTXT, + XPATH_STACK_ERROR } xmlXPathError; /* @@ -380,6 +381,8 @@ struct _xmlXPathParserContext { xmlXPathCompExprPtr comp; /* the precompiled expression */ int xptr; /* it this an XPointer expression */ xmlNodePtr ancestor; /* used for walking preceding axis */ + + int valueFrame; /* used to limit Pop on the stack */ }; /************************************************************************ diff -Naurp libxml2-2.7.8/xpath.c libxml2-2.7.8.oden/xpath.c --- libxml2-2.7.8/xpath.c 2011-10-09 13:01:47.000000000 +0000 +++ libxml2-2.7.8.oden/xpath.c 2011-10-09 13:01:09.000000000 +0000 @@ -252,6 +252,7 @@ static const char *xmlXPathErrorMessages "Encoding error\n", "Char out of XML range\n", "Invalid or incomplete context\n", + "Stack usage errror\n", "?? Unknown error ??\n" /* Must be last in the list! */ }; #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \ @@ -2398,6 +2399,42 @@ xmlXPathCacheConvertNumber(xmlXPathConte ************************************************************************/ /** + * xmlXPathSetFrame: + * @ctxt: an XPath parser context + * + * Set the callee evaluation frame + * + * Returns the previous frame value to be restored once done + */ +static int +xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) { + int ret; + + if (ctxt == NULL) + return(0); + ret = ctxt->valueFrame; + ctxt->valueFrame = ctxt->valueNr; + return(ret); +} + +/** + * xmlXPathPopFrame: + * @ctxt: an XPath parser context + * @frame: the previous frame value + * + * Remove the callee evaluation frame + */ +static void +xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) { + if (ctxt == NULL) + return; + if (ctxt->valueNr < ctxt->valueFrame) { + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR); + } + ctxt->valueFrame = frame; +} + +/** * valuePop: * @ctxt: an XPath evaluation context * @@ -2412,6 +2449,12 @@ valuePop(xmlXPathParserContextPtr ctxt) if ((ctxt == NULL) || (ctxt->valueNr <= 0)) return (NULL); + + if (ctxt->valueNr <= ctxt->valueFrame) { + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR); + return (NULL); + } + ctxt->valueNr--; if (ctxt->valueNr > 0) ctxt->value = ctxt->valueTab[ctxt->valueNr - 1]; @@ -6154,6 +6197,7 @@ xmlXPathCompParserContext(xmlXPathCompEx ret->valueNr = 0; ret->valueMax = 10; ret->value = NULL; + ret->valueFrame = 0; ret->context = ctxt; ret->comp = comp; @@ -11712,6 +11756,7 @@ xmlXPathCompOpEvalPositionalPredicate(xm xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; xmlNodePtr oldContextNode, contextNode = NULL; xmlXPathContextPtr xpctxt = ctxt->context; + int frame; #ifdef LIBXML_XPTR_ENABLED /* @@ -11731,6 +11776,8 @@ xmlXPathCompOpEvalPositionalPredicate(xm */ exprOp = &ctxt->comp->steps[op->ch2]; for (i = 0; i < set->nodeNr; i++) { + xmlXPathObjectPtr tmp; + if (set->nodeTab[i] == NULL) continue; @@ -11758,23 +11805,25 @@ xmlXPathCompOpEvalPositionalPredicate(xm xmlXPathNodeSetAddUnique(contextObj->nodesetval, contextNode); + frame = xmlXPathSetFrame(ctxt); valuePush(ctxt, contextObj); res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); + tmp = valuePop(ctxt); + xmlXPathPopFrame(ctxt, frame); if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { - xmlXPathObjectPtr tmp; - /* pop the result if any */ - tmp = valuePop(ctxt); - if (tmp != contextObj) { + while (tmp != contextObj) { /* * Free up the result * then pop off contextObj, which will be freed later */ xmlXPathReleaseObject(xpctxt, tmp); - valuePop(ctxt); + tmp = valuePop(ctxt); } goto evaluation_error; } + /* push the result back onto the stack */ + valuePush(ctxt, tmp); if (res) pos++; @@ -13378,7 +13427,9 @@ xmlXPathCompOpEval(xmlXPathParserContext xmlXPathFunction func; const xmlChar *oldFunc, *oldFuncURI; int i; + int frame; + frame = xmlXPathSetFrame(ctxt); if (op->ch1 != -1) total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); @@ -13386,15 +13437,18 @@ xmlXPathCompOpEval(xmlXPathParserContext xmlGenericError(xmlGenericErrorContext, "xmlXPathCompOpEval: parameter error\n"); ctxt->error = XPATH_INVALID_OPERAND; + xmlXPathPopFrame(ctxt, frame); return (total); } - for (i = 0; i < op->value; i++) + for (i = 0; i < op->value; i++) { if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlXPathCompOpEval: parameter error\n"); ctxt->error = XPATH_INVALID_OPERAND; + xmlXPathPopFrame(ctxt, frame); return (total); } + } if (op->cache != NULL) XML_CAST_FPTR(func) = op->cache; else { @@ -13410,6 +13464,7 @@ xmlXPathCompOpEval(xmlXPathParserContext xmlGenericError(xmlGenericErrorContext, "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", (char *)op->value4, (char *)op->value5); + xmlXPathPopFrame(ctxt, frame); return (total); } func = xmlXPathFunctionLookupNS(ctxt->context, @@ -13431,6 +13486,7 @@ xmlXPathCompOpEval(xmlXPathParserContext func(ctxt, op->value); ctxt->context->function = oldFunc; ctxt->context->functionURI = oldFuncURI; + xmlXPathPopFrame(ctxt, frame); return (total); } case XPATH_OP_ARG: @@ -14334,6 +14390,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt->valueNr = 0; ctxt->valueMax = 10; ctxt->value = NULL; + ctxt->valueFrame = 0; } #ifdef XPATH_STREAMING if (ctxt->comp->stream) { diff -Naurp libxml2-2.7.8/xpointer.c libxml2-2.7.8.oden/xpointer.c --- libxml2-2.7.8/xpointer.c 2010-10-12 06:25:33.000000000 +0000 +++ libxml2-2.7.8.oden/xpointer.c 2011-10-09 13:01:09.000000000 +0000 @@ -1269,6 +1269,7 @@ xmlXPtrEvalXPointer(xmlXPathParserContex ctxt->valueNr = 0; ctxt->valueMax = 10; ctxt->value = NULL; + ctxt->valueFrame = 0; } SKIP_BLANKS; if (CUR == '/') {