1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-24 13:33:01 +03:00

Rework final handling of XPath results

Move cleanup of XPath stack to xmlXPathFreeParserContext. This avoids
memory leaks if valuePop fails in some error cases. Found with
libFuzzer and ASan.

Rework handling of the final XPath result object in
xmlXPathCompiledEvalInternal and xmlXPathEval to avoid useless error
messages.
This commit is contained in:
Nick Wellnhofer
2017-05-27 15:26:11 +02:00
parent 640a368c80
commit c851970c6e

92
xpath.c
View File

@@ -6296,7 +6296,15 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
*/ */
void void
xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) { xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
int i;
if (ctxt->valueTab != NULL) { if (ctxt->valueTab != NULL) {
for (i = 0; i < ctxt->valueNr; i++) {
if (ctxt->context)
xmlXPathReleaseObject(ctxt->context, ctxt->valueTab[i]);
else
xmlXPathFreeObject(ctxt->valueTab[i]);
}
xmlFree(ctxt->valueTab); xmlFree(ctxt->valueTab);
} }
if (ctxt->comp != NULL) { if (ctxt->comp != NULL) {
@@ -14926,10 +14934,11 @@ xmlXPathCompile(const xmlChar *str) {
static int static int
xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp, xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,
xmlXPathObjectPtr *resObj, xmlXPathObjectPtr *resObjPtr,
int toBool) int toBool)
{ {
xmlXPathParserContextPtr pctxt; xmlXPathParserContextPtr pctxt;
xmlXPathObjectPtr resObj;
#ifndef LIBXML_THREAD_ENABLED #ifndef LIBXML_THREAD_ENABLED
static int reentance = 0; static int reentance = 0;
#endif #endif
@@ -14957,43 +14966,25 @@ xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
pctxt = xmlXPathCompParserContext(comp, ctxt); pctxt = xmlXPathCompParserContext(comp, ctxt);
res = xmlXPathRunEval(pctxt, toBool); res = xmlXPathRunEval(pctxt, toBool);
if (resObj) { if (pctxt->error != XPATH_EXPRESSION_OK) {
if (pctxt->value == NULL) { resObj = NULL;
xmlGenericError(xmlGenericErrorContext, } else {
"xmlXPathCompiledEval: evaluation failed\n"); resObj = valuePop(pctxt);
*resObj = NULL; if (resObj == NULL) {
} else { xmlGenericError(xmlGenericErrorContext,
*resObj = valuePop(pctxt); "xmlXPathCompiledEval: No result on the stack.\n");
} } else if (pctxt->valueNr > 0) {
xmlGenericError(xmlGenericErrorContext,
"xmlXPathCompiledEval: %d object(s) left on the stack.\n",
pctxt->valueNr);
}
} }
/* if (resObjPtr)
* Pop all remaining objects from the stack. *resObjPtr = resObj;
*/ else
if (pctxt->valueNr > 0) { xmlXPathReleaseObject(ctxt, resObj);
xmlXPathObjectPtr tmp;
int stack = 0;
do {
tmp = valuePop(pctxt);
if (tmp != NULL) {
stack++;
xmlXPathReleaseObject(ctxt, tmp);
}
} while (tmp != NULL);
if ((stack != 0) &&
((toBool) || ((resObj) && (*resObj))))
{
xmlGenericError(xmlGenericErrorContext,
"xmlXPathCompiledEval: %d objects left on the stack.\n",
stack);
}
}
if ((pctxt->error != XPATH_EXPRESSION_OK) && (resObj) && (*resObj)) {
xmlXPathFreeObject(*resObj);
*resObj = NULL;
}
pctxt->comp = NULL; pctxt->comp = NULL;
xmlXPathFreeParserContext(pctxt); xmlXPathFreeParserContext(pctxt);
#ifndef LIBXML_THREAD_ENABLED #ifndef LIBXML_THREAD_ENABLED
@@ -15093,8 +15084,7 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
xmlXPathObjectPtr xmlXPathObjectPtr
xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) { xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
xmlXPathParserContextPtr ctxt; xmlXPathParserContextPtr ctxt;
xmlXPathObjectPtr res, tmp, init = NULL; xmlXPathObjectPtr res;
int stack = 0;
CHECK_CTXT(ctx) CHECK_CTXT(ctx)
@@ -15105,9 +15095,7 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
return NULL; return NULL;
xmlXPathEvalExpr(ctxt); xmlXPathEvalExpr(ctxt);
if (ctxt->value == NULL) { if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlGenericError(xmlGenericErrorContext,
"xmlXPathEval: evaluation failed\n");
res = NULL; res = NULL;
} else if ((*ctxt->cur != 0) && (ctxt->comp != NULL) } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL)
#ifdef XPATH_STREAMING #ifdef XPATH_STREAMING
@@ -15118,24 +15106,14 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
res = NULL; res = NULL;
} else { } else {
res = valuePop(ctxt); res = valuePop(ctxt);
} if (res == NULL) {
xmlGenericError(xmlGenericErrorContext,
do { "xmlXPathCompiledEval: No result on the stack.\n");
tmp = valuePop(ctxt); } else if (ctxt->valueNr > 0) {
if (tmp != NULL) { xmlGenericError(xmlGenericErrorContext,
if (tmp != init) "xmlXPathCompiledEval: %d object(s) left on the stack.\n",
stack++; ctxt->valueNr);
xmlXPathReleaseObject(ctx, tmp);
} }
} while (tmp != NULL);
if ((stack != 0) && (res != NULL)) {
xmlGenericError(xmlGenericErrorContext,
"xmlXPathEval: %d object left on the stack\n",
stack);
}
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeObject(res);
res = NULL;
} }
xmlXPathFreeParserContext(ctxt); xmlXPathFreeParserContext(ctxt);