From ac29e4bdcd5ed980608d4ac5214f1e4923edbe23 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 21 May 2017 00:16:54 +0200 Subject: [PATCH] Fix memory leaks in EXSLT error paths Found with libFuzzer and ASan. --- libexslt/dynamic.c | 23 +++++++---------------- libexslt/functions.c | 2 ++ libexslt/sets.c | 30 ++++++++++-------------------- 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/libexslt/dynamic.c b/libexslt/dynamic.c index 4a4944e8..ed5965e0 100644 --- a/libexslt/dynamic.c +++ b/libexslt/dynamic.c @@ -113,24 +113,12 @@ exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs) return; } str = xmlXPathPopString(ctxt); - if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); - return; - } + if (xmlXPathCheckError(ctxt)) + goto cleanup; nodeset = xmlXPathPopNodeSet(ctxt); - if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); - return; - } - if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) { - if (nodeset != NULL) - xmlXPathFreeNodeSet(nodeset); - if (str != NULL) - xmlFree(str); - valuePush(ctxt, xmlXPathNewNodeSet(NULL)); - return; - } + if (xmlXPathCheckError(ctxt)) + goto cleanup; ret = xmlXPathNewNodeSet(NULL); if (ret == NULL) { @@ -139,6 +127,9 @@ exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs) goto cleanup; } + if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) + goto cleanup; + oldDoc = ctxt->context->doc; oldNode = ctxt->context->node; oldContextSize = ctxt->context->contextSize; diff --git a/libexslt/functions.c b/libexslt/functions.c index c20ca16b..9365d6e2 100644 --- a/libexslt/functions.c +++ b/libexslt/functions.c @@ -540,6 +540,7 @@ exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) { xsltGenericError(xsltGenericErrorContext, "exsltFuncFunctionComp: no stylesheet data\n"); xmlFree(name); + xmlFree(func); return; } @@ -548,6 +549,7 @@ exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) { "Failed to register function {%s}%s\n", ns->href, name); style->errors++; + xmlFree(func); } else { xsltGenericDebug(xsltGenericDebugContext, "exsltFuncFunctionComp: register {%s}%s\n", diff --git a/libexslt/sets.c b/libexslt/sets.c index a5a79130..8bb540d8 100644 --- a/libexslt/sets.c +++ b/libexslt/sets.c @@ -34,14 +34,12 @@ exsltSetsDifferenceFunction (xmlXPathParserContextPtr ctxt, int nargs) { } arg2 = xmlXPathPopNodeSet(ctxt); - if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + if (xmlXPathCheckError(ctxt)) return; - } arg1 = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + xmlXPathFreeNodeSet(arg2); return; } @@ -71,14 +69,12 @@ exsltSetsIntersectionFunction (xmlXPathParserContextPtr ctxt, int nargs) { } arg2 = xmlXPathPopNodeSet(ctxt); - if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + if (xmlXPathCheckError(ctxt)) return; - } arg1 = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + xmlXPathFreeNodeSet(arg2); return; } @@ -150,14 +146,12 @@ exsltSetsHasSameNodesFunction (xmlXPathParserContextPtr ctxt, } arg2 = xmlXPathPopNodeSet(ctxt); - if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + if (xmlXPathCheckError(ctxt)) return; - } arg1 = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + xmlXPathFreeNodeSet(arg2); return; } @@ -186,14 +180,12 @@ exsltSetsLeadingFunction (xmlXPathParserContextPtr ctxt, int nargs) { } arg2 = xmlXPathPopNodeSet(ctxt); - if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + if (xmlXPathCheckError(ctxt)) return; - } arg1 = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + xmlXPathFreeNodeSet(arg2); return; } @@ -233,14 +225,12 @@ exsltSetsTrailingFunction (xmlXPathParserContextPtr ctxt, int nargs) { } arg2 = xmlXPathPopNodeSet(ctxt); - if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + if (xmlXPathCheckError(ctxt)) return; - } arg1 = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { - xmlXPathSetTypeError(ctxt); + xmlXPathFreeNodeSet(arg2); return; }