File libxslt-CVE-2025-10911.patch of Package libxslt.41023

Index: libxslt-1.1.32/libxslt/transform.c
===================================================================
--- libxslt-1.1.32.orig/libxslt/transform.c
+++ libxslt-1.1.32/libxslt/transform.c
@@ -521,19 +521,20 @@ xsltTransformCacheFree(xsltTransformCach
     /*
     * 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);
 	}
     }
     /*
@@ -2253,32 +2254,31 @@ xsltLocalVariablePush(xsltTransformConte
  * 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;
+    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->psvi == XSLT_RVT_LOCAL) {
-            xsltReleaseRVT(ctxt, tmp);
-        } else if (tmp->psvi == XSLT_RVT_GLOBAL) {
-            xsltRegisterPersistRVT(ctxt, tmp);
-        } else if (tmp->psvi != XSLT_RVT_FUNC_RESULT) {
+        cur = cur->next;
+        if (tmp->RVT->psvi == XSLT_RVT_LOCAL) {
+            xsltReleaseRVTList(ctxt, tmp);
+        } else if (tmp->RVT->psvi == XSLT_RVT_GLOBAL) {
+            xsltRegisterPersistRVT(ctxt, tmp->RVT);
+            xmlFree(tmp);
+        } else if (tmp->RVT->psvi != XSLT_RVT_FUNC_RESULT) {
             xmlGenericError(xmlGenericErrorContext,
-                    "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
-                    tmp->psvi);
+                    "xsltReleaseLocalRVTs: Unexpected RVT flag %d\n",
+                    tmp->RVT->psvi);
         }
     } while (cur != base);
 
-    if (base != NULL)
-        base->prev = NULL;
-    ctxt->localRVT = base;
+    ctxt->localRVTList = base;
 }
 
 /**
@@ -2304,7 +2304,7 @@ xsltApplySequenceConstructor(xsltTransfo
     xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode;
     xmlNodePtr cur, insert, copy = NULL;
     int level = 0, oldVarsNr;
-    xmlDocPtr oldLocalFragmentTop;
+    xsltRVTListPtr oldLocalFragmentTop;
 
 #ifdef XSLT_REFACTORED
     xsltStylePreCompPtr info;
@@ -2350,7 +2350,7 @@ xsltApplySequenceConstructor(xsltTransfo
     }
     ctxt->depth++;
 
-    oldLocalFragmentTop = ctxt->localRVT;
+    oldLocalFragmentTop = ctxt->localRVTList;
     oldInsert = insert = ctxt->insert;
     oldInst = oldCurInst = ctxt->inst;
     oldContextNode = ctxt->node;
@@ -2573,7 +2573,7 @@ xsltApplySequenceConstructor(xsltTransfo
 		    /*
 		    * Cleanup temporary tree fragments.
 		    */
-		    if (oldLocalFragmentTop != ctxt->localRVT)
+		    if (oldLocalFragmentTop != ctxt->localRVTList)
 			xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
 
 		    ctxt->insert = oldInsert;
@@ -2668,7 +2668,7 @@ xsltApplySequenceConstructor(xsltTransfo
 		    /*
 		    * Cleanup temporary tree fragments.
 		    */
-		    if (oldLocalFragmentTop != ctxt->localRVT)
+		    if (oldLocalFragmentTop != ctxt->localRVTList)
 			xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
 
 		    ctxt->insert = oldInsert;
@@ -2734,7 +2734,7 @@ xsltApplySequenceConstructor(xsltTransfo
 		/*
 		* Cleanup temporary tree fragments.
 		*/
-		if (oldLocalFragmentTop != ctxt->localRVT)
+		if (oldLocalFragmentTop != ctxt->localRVTList)
 		    xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
 
                 ctxt->insert = oldInsert;
@@ -2862,7 +2862,7 @@ xsltApplySequenceConstructor(xsltTransfo
 		/*
 		* Cleanup temporary tree fragments.
 		*/
-		if (oldLocalFragmentTop != ctxt->localRVT)
+		if (oldLocalFragmentTop != ctxt->localRVTList)
 		    xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
 
                 ctxt->insert = oldInsert;
@@ -3042,7 +3042,7 @@ xsltApplyXSLTTemplate(xsltTransformConte
     long start = 0;
     xmlNodePtr cur;
     xsltStackElemPtr tmpParam = NULL;
-    xmlDocPtr oldUserFragmentTop;
+    xsltRVTListPtr oldUserFragmentTop;
 
 #ifdef XSLT_REFACTORED
     xsltStyleItemParamPtr iparam;
@@ -3087,8 +3087,8 @@ xsltApplyXSLTTemplate(xsltTransformConte
         return;
 	}
 
-    oldUserFragmentTop = ctxt->tmpRVT;
-    ctxt->tmpRVT = NULL;
+    oldUserFragmentTop = ctxt->tmpRVTList;
+    ctxt->tmpRVTList = NULL;
 
     /*
     * Initiate a distinct scope of local params/variables.
@@ -3195,16 +3195,16 @@ xsltApplyXSLTTemplate(xsltTransformConte
     * 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.
@@ -5276,7 +5276,7 @@ xsltIf(xsltTransformContextPtr ctxt, xml
 
 #ifdef XSLT_FAST_IF
     {
-	xmlDocPtr oldLocalFragmentTop = ctxt->localRVT;
+	xsltRVTListPtr oldLocalFragmentTop = ctxt->localRVTList;
 
 	res = xsltPreCompEvalToBoolean(ctxt, contextNode, comp);
 
@@ -5284,7 +5284,7 @@ xsltIf(xsltTransformContextPtr ctxt, xml
 	* Cleanup fragments created during evaluation of the
 	* "select" expression.
 	*/
-	if (oldLocalFragmentTop != ctxt->localRVT)
+	if (oldLocalFragmentTop != ctxt->localRVTList)
 	    xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
     }
 
Index: libxslt-1.1.32/libxslt/variables.c
===================================================================
--- libxslt-1.1.32.orig/libxslt/variables.c
+++ libxslt-1.1.32/libxslt/variables.c
@@ -47,6 +47,21 @@ static const xmlChar *xsltComputingGloba
 #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 *xsltComputingGloba
 xmlDocPtr
 xsltCreateRVT(xsltTransformContextPtr ctxt)
 {
+    xsltRVTListPtr rvtList;
     xmlDocPtr container;
 
     /*
@@ -76,12 +92,11 @@ xsltCreateRVT(xsltTransformContextPtr ct
     /*
     * 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 ct
 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->psvi = XSLT_RVT_VARIABLE;
+    list->RVT = RVT;
 
     /*
     * We'll restrict the lifetime of user-created fragments
@@ -131,15 +151,13 @@ xsltRegisterTmpRVT(xsltTransformContextP
     * 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,10 +177,13 @@ 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);
 
     /*
     * When evaluating "select" expressions of xsl:variable
@@ -174,8 +195,8 @@ xsltRegisterLocalRVT(xsltTransformContex
 	(XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))
     {
         RVT->psvi = XSLT_RVT_VARIABLE;
-	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);
     }
     /*
@@ -184,10 +205,8 @@ xsltRegisterLocalRVT(xsltTransformContex
     * then this fragment will be freed, when the instruction exits.
     */
     RVT->psvi = XSLT_RVT_LOCAL;
-    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);
 }
 
@@ -347,50 +366,78 @@ xsltFlagRVTs(xsltTransformContextPtr ctx
  * @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)
 {
     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 (RVT->ids != NULL) {
-	    xmlFreeIDTable((xmlIDTablePtr) RVT->ids);
-	    RVT->ids = NULL;
-	}
-	if (RVT->refs != NULL) {
-	    xmlFreeRefTable((xmlRefTablePtr) RVT->refs);
-	    RVT->refs = NULL;
+       if (list->RVT->children != NULL) {
+           xmlFreeNodeList(list->RVT->children);
+           list->RVT->children = NULL;
+           list->RVT->last = NULL;
+       }
+       if (list->RVT->ids != NULL) {
+           xmlFreeIDTable((xmlIDTablePtr) list->RVT->ids);
+           list->RVT->ids = NULL;
+	}
+	if (list->RVT->refs != NULL) {
+	    xmlFreeRefTable((xmlRefTablePtr) list->RVT->refs);
+	    list->RVT->refs = NULL;
 	}
 
 	/*
 	* Reset the ownership information.
 	*/
-	RVT->psvi = NULL;
+	list->RVT->psvi = NULL;
 
-	RVT->next = (xmlNodePtr) ctxt->cache->RVT;
-	ctxt->cache->RVT = RVT;
+	list->next = ctxt->cache->rvtList;
+	ctxt->cache->rvtList = list;
 
 	ctxt->cache->nbRVT++;
 
@@ -402,11 +449,12 @@ xsltReleaseRVT(xsltTransformContextPtr c
     /*
     * 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);
 }
 
 /**
@@ -424,14 +472,17 @@ xsltReleaseRVT(xsltTransformContextPtr c
 int
 xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
 {
+    xsltRVTListPtr list;
+
     if ((ctxt == NULL) || (RVT == NULL)) return(-1);
 
+    list = xsltRVTListCreate();
+    if (list == NULL) return(-1);
+
     RVT->psvi = 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);
 }
 
@@ -446,52 +497,55 @@ xsltRegisterPersistRVT(xsltTransformCont
 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;
 }
 
 /************************************************************************
@@ -579,19 +633,19 @@ 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;
+	    elem->fragment = cur->next;
 
-            if (cur->psvi == XSLT_RVT_VARIABLE) {
-		xsltReleaseRVT((xsltTransformContextPtr) elem->context,
+            if (cur->RVT->psvi == XSLT_RVT_VARIABLE) {
+		xsltReleaseRVTList((xsltTransformContextPtr) elem->context,
 		    cur);
-            } else if (cur->psvi != XSLT_RVT_FUNC_RESULT) {
+            } else if (cur->RVT->psvi != XSLT_RVT_FUNC_RESULT) {
                 xmlGenericError(xmlGenericErrorContext,
                         "xsltFreeStackElem: Unexpected RVT flag %p\n",
-                        cur->psvi);
+                        cur->RVT->psvi);
             }
 	}
     }
@@ -963,6 +1017,7 @@ xsltEvalVariable(xsltTransformContextPtr
 	} else {
 	    if (variable->tree) {
 		xmlDocPtr container;
+                xsltRVTListPtr rvtList;
 		xmlNodePtr oldInsert;
 		xmlDocPtr  oldOutput;
 		xsltStackElemPtr oldVar = ctxt->contextVariable;
@@ -985,7 +1040,12 @@ xsltEvalVariable(xsltTransformContextPtr
 		* 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->psvi = XSLT_RVT_VARIABLE;
 
 		oldOutput = ctxt->output;
@@ -2361,5 +2421,3 @@ local_variable_found:
 
     return(valueObj);
 }
-
-
Index: libxslt-1.1.32/libxslt/xsltInternals.h
===================================================================
--- libxslt-1.1.32.orig/libxslt/xsltInternals.h
+++ libxslt-1.1.32/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 */
@@ -1919,8 +1926,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
  */
@@ -1979,4 +1989,3 @@ XSLTPUBFUN int XSLTCALL
 #endif
 
 #endif /* __XML_XSLT_H__ */
-
openSUSE Build Service is sponsored by