Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
File diff suppressed because it is too large
Load Diff
@ -1,103 +0,0 @@
|
|||||||
From 5b3b3151e4af0f6c234c97e01e05cf6edc9eceab Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 21 Mar 2023 12:19:50 +0100
|
|
||||||
Subject: [PATCH 1/2] malloc-fail: Fix memory leak in exclPrefixPush
|
|
||||||
|
|
||||||
Found by OSS-Fuzz, see #84.
|
|
||||||
---
|
|
||||||
libxslt/xslt.c | 24 ++++++++----------------
|
|
||||||
1 file changed, 8 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libxslt/xslt.c b/libxslt/xslt.c
|
|
||||||
index 7a1ce011..6d4126a1 100644
|
|
||||||
--- a/libxslt/xslt.c
|
|
||||||
+++ b/libxslt/xslt.c
|
|
||||||
@@ -157,31 +157,23 @@ exclPrefixPush(xsltStylesheetPtr style, xmlChar * value)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
- if (style->exclPrefixMax == 0) {
|
|
||||||
- style->exclPrefixMax = 4;
|
|
||||||
- style->exclPrefixTab =
|
|
||||||
- (xmlChar * *)xmlMalloc(style->exclPrefixMax *
|
|
||||||
- sizeof(style->exclPrefixTab[0]));
|
|
||||||
- if (style->exclPrefixTab == NULL) {
|
|
||||||
- xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
|
|
||||||
- return (-1);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
/* do not push duplicates */
|
|
||||||
for (i = 0;i < style->exclPrefixNr;i++) {
|
|
||||||
if (xmlStrEqual(style->exclPrefixTab[i], value))
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
if (style->exclPrefixNr >= style->exclPrefixMax) {
|
|
||||||
- style->exclPrefixMax *= 2;
|
|
||||||
- style->exclPrefixTab =
|
|
||||||
- (xmlChar * *)xmlRealloc(style->exclPrefixTab,
|
|
||||||
- style->exclPrefixMax *
|
|
||||||
- sizeof(style->exclPrefixTab[0]));
|
|
||||||
- if (style->exclPrefixTab == NULL) {
|
|
||||||
+ xmlChar **tmp;
|
|
||||||
+ size_t max = style->exclPrefixMax ? style->exclPrefixMax * 2 : 4;
|
|
||||||
+
|
|
||||||
+ tmp = xmlRealloc(style->exclPrefixTab,
|
|
||||||
+ max * sizeof(style->exclPrefixTab[0]));
|
|
||||||
+ if (tmp == NULL) {
|
|
||||||
xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
+ style->exclPrefixTab = tmp;
|
|
||||||
+ style->exclPrefixMax = max;
|
|
||||||
}
|
|
||||||
style->exclPrefixTab[style->exclPrefixNr] = value;
|
|
||||||
style->exclPrefix = value;
|
|
||||||
--
|
|
||||||
2.49.0
|
|
||||||
|
|
||||||
|
|
||||||
From 43c2b70b12717940ff9141c3bc2dc7f3a49df2b5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 5 Dec 2024 12:43:19 +0100
|
|
||||||
Subject: [PATCH 2/2] [CVE-2024-55549] Fix UAF related to excluded namespaces
|
|
||||||
|
|
||||||
Definitions of excluded namespaces could be deleted in
|
|
||||||
xsltParseTemplateContent. Store excluded namespace URIs in the
|
|
||||||
stylesheet's dictionary instead of referencing the namespace definition.
|
|
||||||
|
|
||||||
Thanks to Ivan Fratric for the report!
|
|
||||||
|
|
||||||
Fixes #127.
|
|
||||||
---
|
|
||||||
libxslt/xslt.c | 12 +++++++++++-
|
|
||||||
1 file changed, 11 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libxslt/xslt.c b/libxslt/xslt.c
|
|
||||||
index 6d4126a1..11681a13 100644
|
|
||||||
--- a/libxslt/xslt.c
|
|
||||||
+++ b/libxslt/xslt.c
|
|
||||||
@@ -153,10 +153,20 @@ xsltParseContentError(xsltStylesheetPtr style,
|
|
||||||
* in case of error
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
-exclPrefixPush(xsltStylesheetPtr style, xmlChar * value)
|
|
||||||
+exclPrefixPush(xsltStylesheetPtr style, xmlChar * orig)
|
|
||||||
{
|
|
||||||
+ xmlChar *value;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * orig can come from a namespace definition on a node which
|
|
||||||
+ * could be deleted later, for example in xsltParseTemplateContent.
|
|
||||||
+ * Store the string in stylesheet's dict to avoid use after free.
|
|
||||||
+ */
|
|
||||||
+ value = (xmlChar *) xmlDictLookup(style->dict, orig, -1);
|
|
||||||
+ if (value == NULL)
|
|
||||||
+ return(-1);
|
|
||||||
+
|
|
||||||
/* do not push duplicates */
|
|
||||||
for (i = 0;i < style->exclPrefixNr;i++) {
|
|
||||||
if (xmlStrEqual(style->exclPrefixTab[i], value))
|
|
||||||
--
|
|
||||||
2.49.0
|
|
||||||
|
|
||||||
@ -1,718 +0,0 @@
|
|||||||
From 5a50e73fa2e48e5ccdb8f36ebaeeaf8404e33879 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Cheng <zetafunction@gmail.com>
|
|
||||||
Date: Thu, 5 Jun 2025 09:43:53 -0700
|
|
||||||
Subject: [PATCH] Use a dedicated node type to maintain the list of cached RVTs
|
|
||||||
|
|
||||||
While evaluating a stylesheet, result value trees (result tree fragments
|
|
||||||
in the XSLT spec) are represented as xmlDocs and cached on the transform
|
|
||||||
context in a linked list, using xmlDoc's prev and next pointers to
|
|
||||||
maintain the list.
|
|
||||||
|
|
||||||
However, XPath evaluations can inadvertently traverse these links, which
|
|
||||||
are an implementation detail and do not reflect the actual document
|
|
||||||
structure. Using a dedicated node type avoids these unintended
|
|
||||||
traversals.
|
|
||||||
|
|
||||||
Fixes #144.
|
|
||||||
---
|
|
||||||
libxslt/transform.c | 93 ++++++++---------
|
|
||||||
libxslt/variables.c | 224 +++++++++++++++++++++++++---------------
|
|
||||||
libxslt/xsltInternals.h | 23 +++--
|
|
||||||
3 files changed, 201 insertions(+), 139 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libxslt/transform.c b/libxslt/transform.c
|
|
||||||
index 8a424773..b500b35d 100644
|
|
||||||
--- a/libxslt/transform.c
|
|
||||||
+++ b/libxslt/transform.c
|
|
||||||
@@ -521,19 +521,20 @@ xsltTransformCacheFree(xsltTransformCachePtr cache)
|
|
||||||
/*
|
|
||||||
* Free tree fragments.
|
|
||||||
*/
|
|
||||||
- if (cache->RVT) {
|
|
||||||
- xmlDocPtr tmp, cur = cache->RVT;
|
|
||||||
+ if (cache->rvtList) {
|
|
||||||
+ xsltRVTListPtr tmp, cur = cache->rvtList;
|
|
||||||
while (cur) {
|
|
||||||
tmp = cur;
|
|
||||||
- cur = (xmlDocPtr) cur->next;
|
|
||||||
- if (tmp->_private != NULL) {
|
|
||||||
+ cur = cur->next;
|
|
||||||
+ if (tmp->RVT->_private != NULL) {
|
|
||||||
/*
|
|
||||||
- * Tree the document info.
|
|
||||||
+ * Free the document info.
|
|
||||||
*/
|
|
||||||
- xsltFreeDocumentKeys((xsltDocumentPtr) tmp->_private);
|
|
||||||
- xmlFree(tmp->_private);
|
|
||||||
+ xsltFreeDocumentKeys((xsltDocumentPtr) tmp->RVT->_private);
|
|
||||||
+ xmlFree(tmp->RVT->_private);
|
|
||||||
}
|
|
||||||
- xmlFreeDoc(tmp);
|
|
||||||
+ xmlFreeDoc(tmp->RVT);
|
|
||||||
+ xmlFree(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
@@ -2294,43 +2295,39 @@ xsltLocalVariablePush(xsltTransformContextPtr ctxt,
|
|
||||||
* are preserved; all other fragments are freed/cached.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
-xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
|
|
||||||
+xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xsltRVTListPtr base)
|
|
||||||
{
|
|
||||||
- xmlDocPtr cur = ctxt->localRVT, tmp;
|
|
||||||
- xmlDocPtr prev = NULL;
|
|
||||||
+ xsltRVTListPtr cur = ctxt->localRVTList, tmp;
|
|
||||||
|
|
||||||
if (cur == base)
|
|
||||||
return;
|
|
||||||
- if (cur->prev != NULL)
|
|
||||||
- xsltTransformError(ctxt, NULL, NULL, "localRVT not head of list\n");
|
|
||||||
+
|
|
||||||
+ /* Reset localRVTList early because some RVTs might be registered again. */
|
|
||||||
+ ctxt->localRVTList = base;
|
|
||||||
+
|
|
||||||
|
|
||||||
do {
|
|
||||||
tmp = cur;
|
|
||||||
- cur = (xmlDocPtr) cur->next;
|
|
||||||
- if (tmp->compression == XSLT_RVT_LOCAL) {
|
|
||||||
- xsltReleaseRVT(ctxt, tmp);
|
|
||||||
- } else if (tmp->compression == XSLT_RVT_GLOBAL) {
|
|
||||||
- xsltRegisterPersistRVT(ctxt, tmp);
|
|
||||||
- } else if (tmp->compression == XSLT_RVT_FUNC_RESULT) {
|
|
||||||
+ cur = cur->next;
|
|
||||||
+ if (tmp->RVT->compression == XSLT_RVT_LOCAL) {
|
|
||||||
+ xsltReleaseRVTList(ctxt, tmp);
|
|
||||||
+ } else if (tmp->RVT->compression == XSLT_RVT_GLOBAL) {
|
|
||||||
+ xsltRegisterPersistRVT(ctxt, tmp->RVT);
|
|
||||||
+ xmlFree(tmp);
|
|
||||||
+ } else if (tmp->RVT->compression == XSLT_RVT_FUNC_RESULT) {
|
|
||||||
/*
|
|
||||||
* This will either register the RVT again or move it to the
|
|
||||||
* context variable.
|
|
||||||
*/
|
|
||||||
- xsltRegisterLocalRVT(ctxt, tmp);
|
|
||||||
- tmp->compression = XSLT_RVT_FUNC_RESULT;
|
|
||||||
+ xsltRegisterLocalRVT(ctxt, tmp->RVT);
|
|
||||||
+ tmp->RVT->compression = XSLT_RVT_FUNC_RESULT;
|
|
||||||
+ xmlFree(tmp);
|
|
||||||
} else {
|
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
|
||||||
- "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
|
|
||||||
- tmp->compression);
|
|
||||||
+ "xsltReleaseLocalRVTs: Unexpected RVT flag %d\n",
|
|
||||||
+ tmp->RVT->compression);
|
|
||||||
}
|
|
||||||
} while (cur != base);
|
|
||||||
-
|
|
||||||
- if (prev == NULL)
|
|
||||||
- ctxt->localRVT = base;
|
|
||||||
- else
|
|
||||||
- prev->next = (xmlNodePtr) base;
|
|
||||||
- if (base != NULL)
|
|
||||||
- base->prev = (xmlNodePtr) prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -2356,7 +2353,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
|
|
||||||
xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode;
|
|
||||||
xmlNodePtr cur, insert, copy = NULL;
|
|
||||||
int level = 0, oldVarsNr;
|
|
||||||
- xmlDocPtr oldLocalFragmentTop;
|
|
||||||
+ xsltRVTListPtr oldLocalFragmentTop;
|
|
||||||
|
|
||||||
#ifdef XSLT_REFACTORED
|
|
||||||
xsltStylePreCompPtr info;
|
|
||||||
@@ -2402,7 +2399,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
|
|
||||||
}
|
|
||||||
ctxt->depth++;
|
|
||||||
|
|
||||||
- oldLocalFragmentTop = ctxt->localRVT;
|
|
||||||
+ oldLocalFragmentTop = ctxt->localRVTList;
|
|
||||||
oldInsert = insert = ctxt->insert;
|
|
||||||
oldInst = oldCurInst = ctxt->inst;
|
|
||||||
oldContextNode = ctxt->node;
|
|
||||||
@@ -2625,7 +2622,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
|
|
||||||
/*
|
|
||||||
* Cleanup temporary tree fragments.
|
|
||||||
*/
|
|
||||||
- if (oldLocalFragmentTop != ctxt->localRVT)
|
|
||||||
+ if (oldLocalFragmentTop != ctxt->localRVTList)
|
|
||||||
xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
|
|
||||||
|
|
||||||
ctxt->insert = oldInsert;
|
|
||||||
@@ -2720,7 +2717,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
|
|
||||||
/*
|
|
||||||
* Cleanup temporary tree fragments.
|
|
||||||
*/
|
|
||||||
- if (oldLocalFragmentTop != ctxt->localRVT)
|
|
||||||
+ if (oldLocalFragmentTop != ctxt->localRVTList)
|
|
||||||
xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
|
|
||||||
|
|
||||||
ctxt->insert = oldInsert;
|
|
||||||
@@ -2786,7 +2783,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
|
|
||||||
/*
|
|
||||||
* Cleanup temporary tree fragments.
|
|
||||||
*/
|
|
||||||
- if (oldLocalFragmentTop != ctxt->localRVT)
|
|
||||||
+ if (oldLocalFragmentTop != ctxt->localRVTList)
|
|
||||||
xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
|
|
||||||
|
|
||||||
ctxt->insert = oldInsert;
|
|
||||||
@@ -2914,7 +2911,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
|
|
||||||
/*
|
|
||||||
* Cleanup temporary tree fragments.
|
|
||||||
*/
|
|
||||||
- if (oldLocalFragmentTop != ctxt->localRVT)
|
|
||||||
+ if (oldLocalFragmentTop != ctxt->localRVTList)
|
|
||||||
xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
|
|
||||||
|
|
||||||
ctxt->insert = oldInsert;
|
|
||||||
@@ -3094,7 +3091,7 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
|
|
||||||
long start = 0;
|
|
||||||
xmlNodePtr cur;
|
|
||||||
xsltStackElemPtr tmpParam = NULL;
|
|
||||||
- xmlDocPtr oldUserFragmentTop;
|
|
||||||
+ xsltRVTListPtr oldUserFragmentTop;
|
|
||||||
|
|
||||||
#ifdef XSLT_REFACTORED
|
|
||||||
xsltStyleItemParamPtr iparam;
|
|
||||||
@@ -3139,8 +3136,8 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- oldUserFragmentTop = ctxt->tmpRVT;
|
|
||||||
- ctxt->tmpRVT = NULL;
|
|
||||||
+ oldUserFragmentTop = ctxt->tmpRVTList;
|
|
||||||
+ ctxt->tmpRVTList = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initiate a distinct scope of local params/variables.
|
|
||||||
@@ -3247,16 +3244,16 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
|
|
||||||
* user code should now use xsltRegisterLocalRVT() instead
|
|
||||||
* of the obsolete xsltRegisterTmpRVT().
|
|
||||||
*/
|
|
||||||
- if (ctxt->tmpRVT) {
|
|
||||||
- xmlDocPtr curdoc = ctxt->tmpRVT, tmp;
|
|
||||||
+ if (ctxt->tmpRVTList) {
|
|
||||||
+ xsltRVTListPtr curRVTList = ctxt->tmpRVTList, tmp;
|
|
||||||
|
|
||||||
- while (curdoc != NULL) {
|
|
||||||
- tmp = curdoc;
|
|
||||||
- curdoc = (xmlDocPtr) curdoc->next;
|
|
||||||
- xsltReleaseRVT(ctxt, tmp);
|
|
||||||
+ while (curRVTList != NULL) {
|
|
||||||
+ tmp = curRVTList;
|
|
||||||
+ curRVTList = curRVTList->next;
|
|
||||||
+ xsltReleaseRVTList(ctxt, tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- ctxt->tmpRVT = oldUserFragmentTop;
|
|
||||||
+ ctxt->tmpRVTList = oldUserFragmentTop;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pop the xsl:template declaration from the stack.
|
|
||||||
@@ -5392,7 +5389,7 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
|
|
||||||
|
|
||||||
#ifdef XSLT_FAST_IF
|
|
||||||
{
|
|
||||||
- xmlDocPtr oldLocalFragmentTop = ctxt->localRVT;
|
|
||||||
+ xsltRVTListPtr oldLocalFragmentTop = ctxt->localRVTList;
|
|
||||||
|
|
||||||
res = xsltPreCompEvalToBoolean(ctxt, contextNode, comp);
|
|
||||||
|
|
||||||
@@ -5400,7 +5397,7 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
|
|
||||||
* Cleanup fragments created during evaluation of the
|
|
||||||
* "select" expression.
|
|
||||||
*/
|
|
||||||
- if (oldLocalFragmentTop != ctxt->localRVT)
|
|
||||||
+ if (oldLocalFragmentTop != ctxt->localRVTList)
|
|
||||||
xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/libxslt/variables.c b/libxslt/variables.c
|
|
||||||
index 0f4b72f3..e1d9938c 100644
|
|
||||||
--- a/libxslt/variables.c
|
|
||||||
+++ b/libxslt/variables.c
|
|
||||||
@@ -47,6 +47,21 @@ static const xmlChar *xsltComputingGlobalVarMarker =
|
|
||||||
#define XSLT_VAR_IN_SELECT (1<<1)
|
|
||||||
#define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)
|
|
||||||
|
|
||||||
+static xsltRVTListPtr
|
|
||||||
+xsltRVTListCreate(void)
|
|
||||||
+{
|
|
||||||
+ xsltRVTListPtr ret;
|
|
||||||
+
|
|
||||||
+ ret = (xsltRVTListPtr) xmlMalloc(sizeof(xsltRVTList));
|
|
||||||
+ if (ret == NULL) {
|
|
||||||
+ xsltTransformError(NULL, NULL, NULL,
|
|
||||||
+ "xsltRVTListCreate: malloc failed\n");
|
|
||||||
+ return(NULL);
|
|
||||||
+ }
|
|
||||||
+ memset(ret, 0, sizeof(xsltRVTList));
|
|
||||||
+ return(ret);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/************************************************************************
|
|
||||||
* *
|
|
||||||
* Result Value Tree (Result Tree Fragment) interfaces *
|
|
||||||
@@ -64,6 +79,7 @@ static const xmlChar *xsltComputingGlobalVarMarker =
|
|
||||||
xmlDocPtr
|
|
||||||
xsltCreateRVT(xsltTransformContextPtr ctxt)
|
|
||||||
{
|
|
||||||
+ xsltRVTListPtr rvtList;
|
|
||||||
xmlDocPtr container;
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -76,12 +92,11 @@ xsltCreateRVT(xsltTransformContextPtr ctxt)
|
|
||||||
/*
|
|
||||||
* Reuse a RTF from the cache if available.
|
|
||||||
*/
|
|
||||||
- if (ctxt->cache->RVT) {
|
|
||||||
- container = ctxt->cache->RVT;
|
|
||||||
- ctxt->cache->RVT = (xmlDocPtr) container->next;
|
|
||||||
- /* clear the internal pointers */
|
|
||||||
- container->next = NULL;
|
|
||||||
- container->prev = NULL;
|
|
||||||
+ if (ctxt->cache->rvtList) {
|
|
||||||
+ rvtList = ctxt->cache->rvtList;
|
|
||||||
+ container = ctxt->cache->rvtList->RVT;
|
|
||||||
+ ctxt->cache->rvtList = rvtList->next;
|
|
||||||
+ xmlFree(rvtList);
|
|
||||||
if (ctxt->cache->nbRVT > 0)
|
|
||||||
ctxt->cache->nbRVT--;
|
|
||||||
#ifdef XSLT_DEBUG_PROFILE_CACHE
|
|
||||||
@@ -119,11 +134,16 @@ xsltCreateRVT(xsltTransformContextPtr ctxt)
|
|
||||||
int
|
|
||||||
xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
{
|
|
||||||
+ xsltRVTListPtr list;
|
|
||||||
+
|
|
||||||
if ((ctxt == NULL) || (RVT == NULL))
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
- RVT->prev = NULL;
|
|
||||||
+ list = xsltRVTListCreate();
|
|
||||||
+ if (list == NULL) return(-1);
|
|
||||||
+
|
|
||||||
RVT->compression = XSLT_RVT_LOCAL;
|
|
||||||
+ list->RVT = RVT;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We'll restrict the lifetime of user-created fragments
|
|
||||||
@@ -131,15 +151,13 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
* var/param itself.
|
|
||||||
*/
|
|
||||||
if (ctxt->contextVariable != NULL) {
|
|
||||||
- RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
|
|
||||||
- XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
|
|
||||||
+ list->next = XSLT_TCTXT_VARIABLE(ctxt)->fragment;
|
|
||||||
+ XSLT_TCTXT_VARIABLE(ctxt)->fragment = list;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
- RVT->next = (xmlNodePtr) ctxt->tmpRVT;
|
|
||||||
- if (ctxt->tmpRVT != NULL)
|
|
||||||
- ctxt->tmpRVT->prev = (xmlNodePtr) RVT;
|
|
||||||
- ctxt->tmpRVT = RVT;
|
|
||||||
+ list->next = ctxt->tmpRVTList;
|
|
||||||
+ ctxt->tmpRVTList = list;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -159,11 +177,16 @@ int
|
|
||||||
xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
|
|
||||||
xmlDocPtr RVT)
|
|
||||||
{
|
|
||||||
+ xsltRVTListPtr list;
|
|
||||||
+
|
|
||||||
if ((ctxt == NULL) || (RVT == NULL))
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
- RVT->prev = NULL;
|
|
||||||
+ list = xsltRVTListCreate();
|
|
||||||
+ if (list == NULL) return(-1);
|
|
||||||
+
|
|
||||||
RVT->compression = XSLT_RVT_LOCAL;
|
|
||||||
+ list->RVT = RVT;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When evaluating "select" expressions of xsl:variable
|
|
||||||
@@ -174,8 +197,8 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
|
|
||||||
if ((ctxt->contextVariable != NULL) &&
|
|
||||||
(XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))
|
|
||||||
{
|
|
||||||
- RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
|
|
||||||
- XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
|
|
||||||
+ list->next = XSLT_TCTXT_VARIABLE(ctxt)->fragment;
|
|
||||||
+ XSLT_TCTXT_VARIABLE(ctxt)->fragment = list;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
@@ -183,10 +206,8 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
|
|
||||||
* If not reference by a returning instruction (like EXSLT's function),
|
|
||||||
* then this fragment will be freed, when the instruction exits.
|
|
||||||
*/
|
|
||||||
- RVT->next = (xmlNodePtr) ctxt->localRVT;
|
|
||||||
- if (ctxt->localRVT != NULL)
|
|
||||||
- ctxt->localRVT->prev = (xmlNodePtr) RVT;
|
|
||||||
- ctxt->localRVT = RVT;
|
|
||||||
+ list->next = ctxt->localRVTList;
|
|
||||||
+ ctxt->localRVTList = list;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -340,8 +361,9 @@ xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, int val) {
|
|
||||||
* @ctxt: an XSLT transformation context
|
|
||||||
* @RVT: a result value tree (Result Tree Fragment)
|
|
||||||
*
|
|
||||||
- * Either frees the RVT (which is an xmlDoc) or stores
|
|
||||||
- * it in the context's cache for later reuse.
|
|
||||||
+ * Either frees the RVT (which is an xmlDoc) or stores it in the context's
|
|
||||||
+ * cache for later reuse. Preserved for ABI/API compatibility; internal use
|
|
||||||
+ * has all migrated to xsltReleaseRVTList().
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
@@ -349,41 +371,64 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
if (RVT == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
+ xsltRVTListPtr list = xsltRVTListCreate();
|
|
||||||
+ if (list == NULL) {
|
|
||||||
+ if (RVT->_private != NULL) {
|
|
||||||
+ xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);
|
|
||||||
+ xmlFree(RVT->_private);
|
|
||||||
+ }
|
|
||||||
+ xmlFreeDoc(RVT);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xsltReleaseRVTList(ctxt, list);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * xsltReleaseRVTList:
|
|
||||||
+ * @ctxt: an XSLT transformation context
|
|
||||||
+ * @list: a list node containing a result value tree (Result Tree Fragment)
|
|
||||||
+ *
|
|
||||||
+ * Either frees the list node or stores it in the context's cache for later
|
|
||||||
+ * reuse. Optimization to avoid adding a fallible allocation path when the
|
|
||||||
+ * caller already has a RVT list node.
|
|
||||||
+ */
|
|
||||||
+void
|
|
||||||
+xsltReleaseRVTList(xsltTransformContextPtr ctxt, xsltRVTListPtr list)
|
|
||||||
+{
|
|
||||||
+ if (list == NULL)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
if (ctxt && (ctxt->cache->nbRVT < 40)) {
|
|
||||||
/*
|
|
||||||
* Store the Result Tree Fragment.
|
|
||||||
* Free the document info.
|
|
||||||
*/
|
|
||||||
- if (RVT->_private != NULL) {
|
|
||||||
- xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);
|
|
||||||
- xmlFree(RVT->_private);
|
|
||||||
- RVT->_private = NULL;
|
|
||||||
+ if (list->RVT->_private != NULL) {
|
|
||||||
+ xsltFreeDocumentKeys((xsltDocumentPtr) list->RVT->_private);
|
|
||||||
+ xmlFree(list->RVT->_private);
|
|
||||||
+ list->RVT->_private = NULL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Clear the document tree.
|
|
||||||
- * REVISIT TODO: Do we expect ID/IDREF tables to be existent?
|
|
||||||
*/
|
|
||||||
- if (RVT->children != NULL) {
|
|
||||||
- xmlFreeNodeList(RVT->children);
|
|
||||||
- RVT->children = NULL;
|
|
||||||
- RVT->last = NULL;
|
|
||||||
+ if (list->RVT->children != NULL) {
|
|
||||||
+ xmlFreeNodeList(list->RVT->children);
|
|
||||||
+ list->RVT->children = NULL;
|
|
||||||
+ list->RVT->last = NULL;
|
|
||||||
}
|
|
||||||
- if (RVT->ids != NULL) {
|
|
||||||
- xmlFreeIDTable((xmlIDTablePtr) RVT->ids);
|
|
||||||
- RVT->ids = NULL;
|
|
||||||
- }
|
|
||||||
- if (RVT->refs != NULL) {
|
|
||||||
- xmlFreeRefTable((xmlRefTablePtr) RVT->refs);
|
|
||||||
- RVT->refs = NULL;
|
|
||||||
+ if (list->RVT->ids != NULL) {
|
|
||||||
+ xmlFreeIDTable((xmlIDTablePtr) list->RVT->ids);
|
|
||||||
+ list->RVT->ids = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset the ownership information.
|
|
||||||
*/
|
|
||||||
- RVT->compression = 0;
|
|
||||||
+ list->RVT->compression = 0;
|
|
||||||
|
|
||||||
- RVT->next = (xmlNodePtr) ctxt->cache->RVT;
|
|
||||||
- ctxt->cache->RVT = RVT;
|
|
||||||
+ list->next = ctxt->cache->rvtList;
|
|
||||||
+ ctxt->cache->rvtList = list;
|
|
||||||
|
|
||||||
ctxt->cache->nbRVT++;
|
|
||||||
|
|
||||||
@@ -395,11 +440,12 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
/*
|
|
||||||
* Free it.
|
|
||||||
*/
|
|
||||||
- if (RVT->_private != NULL) {
|
|
||||||
- xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);
|
|
||||||
- xmlFree(RVT->_private);
|
|
||||||
+ if (list->RVT->_private != NULL) {
|
|
||||||
+ xsltFreeDocumentKeys((xsltDocumentPtr) list->RVT->_private);
|
|
||||||
+ xmlFree(list->RVT->_private);
|
|
||||||
}
|
|
||||||
- xmlFreeDoc(RVT);
|
|
||||||
+ xmlFreeDoc(list->RVT);
|
|
||||||
+ xmlFree(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -417,14 +463,17 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
int
|
|
||||||
xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
{
|
|
||||||
+ xsltRVTListPtr list;
|
|
||||||
+
|
|
||||||
if ((ctxt == NULL) || (RVT == NULL)) return(-1);
|
|
||||||
|
|
||||||
+ list = xsltRVTListCreate();
|
|
||||||
+ if (list == NULL) return(-1);
|
|
||||||
+
|
|
||||||
RVT->compression = XSLT_RVT_GLOBAL;
|
|
||||||
- RVT->prev = NULL;
|
|
||||||
- RVT->next = (xmlNodePtr) ctxt->persistRVT;
|
|
||||||
- if (ctxt->persistRVT != NULL)
|
|
||||||
- ctxt->persistRVT->prev = (xmlNodePtr) RVT;
|
|
||||||
- ctxt->persistRVT = RVT;
|
|
||||||
+ list->RVT = RVT;
|
|
||||||
+ list->next = ctxt->persistRVTList;
|
|
||||||
+ ctxt->persistRVTList = list;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -439,52 +488,55 @@ xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
|
|
||||||
void
|
|
||||||
xsltFreeRVTs(xsltTransformContextPtr ctxt)
|
|
||||||
{
|
|
||||||
- xmlDocPtr cur, next;
|
|
||||||
+ xsltRVTListPtr cur, next;
|
|
||||||
|
|
||||||
if (ctxt == NULL)
|
|
||||||
return;
|
|
||||||
/*
|
|
||||||
* Local fragments.
|
|
||||||
*/
|
|
||||||
- cur = ctxt->localRVT;
|
|
||||||
+ cur = ctxt->localRVTList;
|
|
||||||
while (cur != NULL) {
|
|
||||||
- next = (xmlDocPtr) cur->next;
|
|
||||||
- if (cur->_private != NULL) {
|
|
||||||
- xsltFreeDocumentKeys(cur->_private);
|
|
||||||
- xmlFree(cur->_private);
|
|
||||||
+ next = cur->next;
|
|
||||||
+ if (cur->RVT->_private != NULL) {
|
|
||||||
+ xsltFreeDocumentKeys(cur->RVT->_private);
|
|
||||||
+ xmlFree(cur->RVT->_private);
|
|
||||||
}
|
|
||||||
- xmlFreeDoc(cur);
|
|
||||||
+ xmlFreeDoc(cur->RVT);
|
|
||||||
+ xmlFree(cur);
|
|
||||||
cur = next;
|
|
||||||
}
|
|
||||||
- ctxt->localRVT = NULL;
|
|
||||||
+ ctxt->localRVTList = NULL;
|
|
||||||
/*
|
|
||||||
* User-created per-template fragments.
|
|
||||||
*/
|
|
||||||
- cur = ctxt->tmpRVT;
|
|
||||||
+ cur = ctxt->tmpRVTList;
|
|
||||||
while (cur != NULL) {
|
|
||||||
- next = (xmlDocPtr) cur->next;
|
|
||||||
- if (cur->_private != NULL) {
|
|
||||||
- xsltFreeDocumentKeys(cur->_private);
|
|
||||||
- xmlFree(cur->_private);
|
|
||||||
+ next = cur->next;
|
|
||||||
+ if (cur->RVT->_private != NULL) {
|
|
||||||
+ xsltFreeDocumentKeys(cur->RVT->_private);
|
|
||||||
+ xmlFree(cur->RVT->_private);
|
|
||||||
}
|
|
||||||
- xmlFreeDoc(cur);
|
|
||||||
+ xmlFreeDoc(cur->RVT);
|
|
||||||
+ xmlFree(cur);
|
|
||||||
cur = next;
|
|
||||||
}
|
|
||||||
- ctxt->tmpRVT = NULL;
|
|
||||||
+ ctxt->tmpRVTList = NULL;
|
|
||||||
/*
|
|
||||||
* Global fragments.
|
|
||||||
*/
|
|
||||||
- cur = ctxt->persistRVT;
|
|
||||||
+ cur = ctxt->persistRVTList;
|
|
||||||
while (cur != NULL) {
|
|
||||||
- next = (xmlDocPtr) cur->next;
|
|
||||||
- if (cur->_private != NULL) {
|
|
||||||
- xsltFreeDocumentKeys(cur->_private);
|
|
||||||
- xmlFree(cur->_private);
|
|
||||||
+ next = cur->next;
|
|
||||||
+ if (cur->RVT->_private != NULL) {
|
|
||||||
+ xsltFreeDocumentKeys(cur->RVT->_private);
|
|
||||||
+ xmlFree(cur->RVT->_private);
|
|
||||||
}
|
|
||||||
- xmlFreeDoc(cur);
|
|
||||||
+ xmlFreeDoc(cur->RVT);
|
|
||||||
+ xmlFree(cur);
|
|
||||||
cur = next;
|
|
||||||
}
|
|
||||||
- ctxt->persistRVT = NULL;
|
|
||||||
+ ctxt->persistRVTList = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
@@ -572,21 +624,22 @@ xsltFreeStackElem(xsltStackElemPtr elem) {
|
|
||||||
* Release the list of temporary Result Tree Fragments.
|
|
||||||
*/
|
|
||||||
if (elem->context) {
|
|
||||||
- xmlDocPtr cur;
|
|
||||||
+ xsltRVTListPtr cur;
|
|
||||||
|
|
||||||
while (elem->fragment != NULL) {
|
|
||||||
cur = elem->fragment;
|
|
||||||
- elem->fragment = (xmlDocPtr) cur->next;
|
|
||||||
-
|
|
||||||
- if (cur->compression == XSLT_RVT_LOCAL) {
|
|
||||||
- xsltReleaseRVT(elem->context, cur);
|
|
||||||
- } else if (cur->compression == XSLT_RVT_FUNC_RESULT) {
|
|
||||||
- xsltRegisterLocalRVT(elem->context, cur);
|
|
||||||
- cur->compression = XSLT_RVT_FUNC_RESULT;
|
|
||||||
+ elem->fragment = cur->next;
|
|
||||||
+
|
|
||||||
+ if (cur->RVT->compression == XSLT_RVT_LOCAL) {
|
|
||||||
+ xsltReleaseRVTList(elem->context, cur);
|
|
||||||
+ } else if (cur->RVT->compression == XSLT_RVT_FUNC_RESULT) {
|
|
||||||
+ xsltRegisterLocalRVT(elem->context, cur->RVT);
|
|
||||||
+ cur->RVT->compression = XSLT_RVT_FUNC_RESULT;
|
|
||||||
+ xmlFree(cur);
|
|
||||||
} else {
|
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
|
||||||
"xsltFreeStackElem: Unexpected RVT flag %d\n",
|
|
||||||
- cur->compression);
|
|
||||||
+ cur->RVT->compression);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -958,6 +1011,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
|
|
||||||
} else {
|
|
||||||
if (variable->tree) {
|
|
||||||
xmlDocPtr container;
|
|
||||||
+ xsltRVTListPtr rvtList;
|
|
||||||
xmlNodePtr oldInsert;
|
|
||||||
xmlDocPtr oldOutput;
|
|
||||||
xsltStackElemPtr oldVar = ctxt->contextVariable;
|
|
||||||
@@ -980,7 +1034,11 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
|
|
||||||
* when the variable is freed, it will also free
|
|
||||||
* the Result Tree Fragment.
|
|
||||||
*/
|
|
||||||
- variable->fragment = container;
|
|
||||||
+ rvtList = xsltRVTListCreate();
|
|
||||||
+ if (rvtList == NULL)
|
|
||||||
+ goto error;
|
|
||||||
+ rvtList->RVT = container;
|
|
||||||
+ variable->fragment = rvtList;
|
|
||||||
container->compression = XSLT_RVT_LOCAL;
|
|
||||||
|
|
||||||
oldOutput = ctxt->output;
|
|
||||||
@@ -2356,5 +2414,3 @@ local_variable_found:
|
|
||||||
|
|
||||||
return(valueObj);
|
|
||||||
}
|
|
||||||
-
|
|
||||||
-
|
|
||||||
diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
|
|
||||||
index ae9b76af..f512ed41 100644
|
|
||||||
--- a/libxslt/xsltInternals.h
|
|
||||||
+++ b/libxslt/xsltInternals.h
|
|
||||||
@@ -1421,6 +1421,8 @@ struct _xsltStylePreComp {
|
|
||||||
|
|
||||||
#endif /* XSLT_REFACTORED */
|
|
||||||
|
|
||||||
+typedef struct _xsltRVTList xsltRVTList;
|
|
||||||
+typedef xsltRVTList *xsltRVTListPtr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The in-memory structure corresponding to an XSLT Variable
|
|
||||||
@@ -1438,7 +1440,7 @@ struct _xsltStackElem {
|
|
||||||
xmlNodePtr tree; /* the sequence constructor if no eval
|
|
||||||
string or the location */
|
|
||||||
xmlXPathObjectPtr value; /* The value if computed */
|
|
||||||
- xmlDocPtr fragment; /* The Result Tree Fragments (needed for XSLT 1.0)
|
|
||||||
+ xsltRVTListPtr fragment; /* The Result Tree Fragments (needed for XSLT 1.0)
|
|
||||||
which are bound to the variable's lifetime. */
|
|
||||||
int level; /* the depth in the tree;
|
|
||||||
-1 if persistent (e.g. a given xsl:with-param) */
|
|
||||||
@@ -1644,10 +1646,15 @@ struct _xsltStylesheet {
|
|
||||||
xmlHashTablePtr namedTemplates; /* hash table of named templates */
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct _xsltRVTList {
|
|
||||||
+ xmlDocPtr RVT;
|
|
||||||
+ xsltRVTListPtr next;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
typedef struct _xsltTransformCache xsltTransformCache;
|
|
||||||
typedef xsltTransformCache *xsltTransformCachePtr;
|
|
||||||
struct _xsltTransformCache {
|
|
||||||
- xmlDocPtr RVT;
|
|
||||||
+ xsltRVTListPtr rvtList;
|
|
||||||
int nbRVT;
|
|
||||||
xsltStackElemPtr stackItems;
|
|
||||||
int nbStackItems;
|
|
||||||
@@ -1747,8 +1754,8 @@ struct _xsltTransformContext {
|
|
||||||
* handling of temporary Result Value Tree
|
|
||||||
* (XSLT 1.0 term: "Result Tree Fragment")
|
|
||||||
*/
|
|
||||||
- xmlDocPtr tmpRVT; /* list of RVT without persistance */
|
|
||||||
- xmlDocPtr persistRVT; /* list of persistant RVTs */
|
|
||||||
+ xsltRVTListPtr tmpRVTList; /* list of RVT without persistance */
|
|
||||||
+ xsltRVTListPtr persistRVTList; /* list of persistant RVTs */
|
|
||||||
int ctxtflags; /* context processing flags */
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -1781,7 +1788,7 @@ struct _xsltTransformContext {
|
|
||||||
xmlDocPtr initialContextDoc;
|
|
||||||
xsltTransformCachePtr cache;
|
|
||||||
void *contextVariable; /* the current variable item */
|
|
||||||
- xmlDocPtr localRVT; /* list of local tree fragments; will be freed when
|
|
||||||
+ xsltRVTListPtr localRVTList; /* list of local tree fragments; will be freed when
|
|
||||||
the instruction which created the fragment
|
|
||||||
exits */
|
|
||||||
xmlDocPtr localRVTBase; /* Obsolete */
|
|
||||||
@@ -1923,8 +1930,11 @@ XSLTPUBFUN int XSLTCALL
|
|
||||||
XSLTPUBFUN void XSLTCALL
|
|
||||||
xsltFreeRVTs (xsltTransformContextPtr ctxt);
|
|
||||||
XSLTPUBFUN void XSLTCALL
|
|
||||||
- xsltReleaseRVT (xsltTransformContextPtr ctxt,
|
|
||||||
+ xsltReleaseRVT (xsltTransformContextPtr ctxt,
|
|
||||||
xmlDocPtr RVT);
|
|
||||||
+XSLTPUBFUN void XSLTCALL
|
|
||||||
+ xsltReleaseRVTList (xsltTransformContextPtr ctxt,
|
|
||||||
+ xsltRVTListPtr list);
|
|
||||||
/*
|
|
||||||
* Extra functions for Attribute Value Templates
|
|
||||||
*/
|
|
||||||
@@ -1983,4 +1993,3 @@ XSLTPUBFUN int XSLTCALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __XML_XSLT_H__ */
|
|
||||||
-
|
|
||||||
--
|
|
||||||
2.54.0
|
|
||||||
|
|
||||||
@ -1,130 +0,0 @@
|
|||||||
From c7c7f1f78dd202a053996fcefe57eb994aec8ef2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
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
|
|
||||||
|
|
||||||
@ -8,7 +8,7 @@
|
|||||||
Name: libxslt
|
Name: libxslt
|
||||||
Summary: Library providing the Gnome XSLT engine
|
Summary: Library providing the Gnome XSLT engine
|
||||||
Version: 1.1.32
|
Version: 1.1.32
|
||||||
Release: 6.4%{?dist}
|
Release: 6%{?dist}
|
||||||
|
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: http://xmlsoft.org/XSLT
|
URL: http://xmlsoft.org/XSLT
|
||||||
@ -33,14 +33,6 @@ Patch3: libxslt-1.1.32-CVE-2019-18197.patch
|
|||||||
Patch4: libxslt-1.1.32-CVE-2019-11068.patch
|
Patch4: libxslt-1.1.32-CVE-2019-11068.patch
|
||||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1860467
|
# https://bugzilla.redhat.com/show_bug.cgi?id=1860467
|
||||||
Patch5: libxslt-1.1.32-unexpected-rvt-flag.patch
|
Patch5: libxslt-1.1.32-unexpected-rvt-flag.patch
|
||||||
# https://issues.redhat.com/browse/RHEL-83506
|
|
||||||
Patch6: libxslt-1.1.32-CVE-2024-55549.patch
|
|
||||||
# https://issues.redhat.com/browse/RHEL-83492
|
|
||||||
Patch7: libxslt-1.1.32-CVE-2025-24855.patch
|
|
||||||
# https://issues.redhat.com/browse/RHEL-89374
|
|
||||||
Patch8: libxslt-1.1.32-CVE-2023-40403.patch
|
|
||||||
# https://redhat.atlassian.net/browse/RHEL-171739
|
|
||||||
Patch9: libxslt-1.1.32-CVE-2025-10911.patch
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
This C library allows to transform XML files into other XML files
|
This C library allows to transform XML files into other XML files
|
||||||
@ -145,19 +137,6 @@ rm -vrf %{buildroot}%{_docdir}
|
|||||||
%endif # with python2
|
%endif # with python2
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Tue May 19 2026 David King <dking@redhat.com> - 1.1.32-6.4
|
|
||||||
- Fix CVE-2025-10911 (RHEL-171739)
|
|
||||||
|
|
||||||
* Thu Aug 07 2025 David King <dking@redhat.com> - 1.1.32-6.3
|
|
||||||
- Fix misplaced endif (RHEL-107912)
|
|
||||||
|
|
||||||
* Tue Jun 03 2025 David King <dking@redhat.com> - 1.1.32-6.2
|
|
||||||
- Fix CVE-2023-40403 (aka 2022-4909) (RHEL-89374)
|
|
||||||
|
|
||||||
* Fri Apr 04 2025 David King <dking@redhat.com> - 1.1.32-6.1
|
|
||||||
- Fix CVE-2024-55549 (RHEL-83506)
|
|
||||||
- Fix CVE-2025-24855 (RHEL-83492)
|
|
||||||
|
|
||||||
* Mon Aug 24 2020 David King <dking@redhat.com> - 1.1.32-6
|
* Mon Aug 24 2020 David King <dking@redhat.com> - 1.1.32-6
|
||||||
- Fix unexpected RVT flag error (#1860467)
|
- Fix unexpected RVT flag error (#1860467)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user