From c7c7f1f78dd202a053996fcefe57eb994aec8ef2 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 17 Dec 2024 15:56:21 +0100 Subject: [PATCH] [CVE-2025-24855] Fix use-after-free of XPath context node There are several places where the XPath context node isn't restored after modifying it, leading to use-after-free errors with nested XPath evaluations and dynamically allocated context nodes. Restore XPath context node in - xsltNumberFormatGetValue - xsltEvalXPathPredicate - xsltEvalXPathStringNs - xsltComputeSortResultInternal In some places, the transformation context node was saved and restored which shouldn't be necessary. Thanks to Ivan Fratric for the report! Fixes #128. --- libxslt/numbers.c | 5 +++++ libxslt/templates.c | 9 ++++++--- libxslt/xsltutils.c | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libxslt/numbers.c b/libxslt/numbers.c index 0e1fa136..741124d1 100644 --- a/libxslt/numbers.c +++ b/libxslt/numbers.c @@ -733,9 +733,12 @@ xsltNumberFormatGetValue(xmlXPathContextPtr context, int amount = 0; xmlBufferPtr pattern; xmlXPathObjectPtr obj; + xmlNodePtr oldNode; pattern = xmlBufferCreate(); if (pattern != NULL) { + oldNode = context->node; + xmlBufferCCat(pattern, "number("); xmlBufferCat(pattern, value); xmlBufferCCat(pattern, ")"); @@ -748,6 +751,8 @@ xsltNumberFormatGetValue(xmlXPathContextPtr context, xmlXPathFreeObject(obj); } xmlBufferFree(pattern); + + context->node = oldNode; } return amount; } diff --git a/libxslt/templates.c b/libxslt/templates.c index f08b9bda..1c8d96e2 100644 --- a/libxslt/templates.c +++ b/libxslt/templates.c @@ -61,6 +61,7 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, int oldNsNr; xmlNsPtr *oldNamespaces; xmlNodePtr oldInst; + xmlNodePtr oldNode; int oldProximityPosition, oldContextSize; if ((ctxt == NULL) || (ctxt->inst == NULL)) { @@ -69,6 +70,7 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, return(0); } + oldNode = ctxt->xpathCtxt->node; oldContextSize = ctxt->xpathCtxt->contextSize; oldProximityPosition = ctxt->xpathCtxt->proximityPosition; oldNsNr = ctxt->xpathCtxt->nsNr; @@ -96,8 +98,9 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, ctxt->state = XSLT_STATE_STOPPED; ret = 0; } - ctxt->xpathCtxt->nsNr = oldNsNr; + ctxt->xpathCtxt->node = oldNode; + ctxt->xpathCtxt->nsNr = oldNsNr; ctxt->xpathCtxt->namespaces = oldNamespaces; ctxt->inst = oldInst; ctxt->xpathCtxt->contextSize = oldContextSize; @@ -137,7 +140,7 @@ xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, } oldInst = ctxt->inst; - oldNode = ctxt->node; + oldNode = ctxt->xpathCtxt->node; oldPos = ctxt->xpathCtxt->proximityPosition; oldSize = ctxt->xpathCtxt->contextSize; oldNsNr = ctxt->xpathCtxt->nsNr; @@ -167,7 +170,7 @@ xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, "xsltEvalXPathString: returns %s\n", ret)); #endif ctxt->inst = oldInst; - ctxt->node = oldNode; + ctxt->xpathCtxt->node = oldNode; ctxt->xpathCtxt->contextSize = oldSize; ctxt->xpathCtxt->proximityPosition = oldPos; ctxt->xpathCtxt->nsNr = oldNsNr; diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c index 0e9dc62f..a20da961 100644 --- a/libxslt/xsltutils.c +++ b/libxslt/xsltutils.c @@ -1065,8 +1065,8 @@ xsltComputeSortResultInternal(xsltTransformContextPtr ctxt, xmlNodePtr sort, return(NULL); } - oldNode = ctxt->node; oldInst = ctxt->inst; + oldNode = ctxt->xpathCtxt->node; oldPos = ctxt->xpathCtxt->proximityPosition; oldSize = ctxt->xpathCtxt->contextSize; oldNsNr = ctxt->xpathCtxt->nsNr; @@ -1137,8 +1137,8 @@ xsltComputeSortResultInternal(xsltTransformContextPtr ctxt, xmlNodePtr sort, results[i] = NULL; } } - ctxt->node = oldNode; ctxt->inst = oldInst; + ctxt->xpathCtxt->node = oldNode; ctxt->xpathCtxt->contextSize = oldSize; ctxt->xpathCtxt->proximityPosition = oldPos; ctxt->xpathCtxt->nsNr = oldNsNr; -- GitLab