From 8986995b07126852762e8a59eaee83be0b8de9a3 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 31 Aug 2022 15:35:37 +0200
Subject: [PATCH] Store RVT ownership in 'compression' member

'compression' is another unused member in struct _xmlDoc which is even
better suited to store ownership status. More importantly, this frees up
the 'psvi' member.

This changes the public API but this feature is only required to
implement EXSLT functions.

CVE: CVE-2023-40403
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/commit/ccec6fa31d11ab0a5299f15ea184c7a457e92940]
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>

---
 libexslt/functions.c    |  2 +-
 libxslt/transform.c     |  8 ++++----
 libxslt/variables.c     | 44 ++++++++++++++++++++---------------------
 libxslt/variables.h     |  6 +++---
 libxslt/xsltInternals.h |  2 +-
 5 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/libexslt/functions.c b/libexslt/functions.c
index 958bf60..859a992 100644
--- a/libexslt/functions.c
+++ b/libexslt/functions.c
@@ -775,7 +775,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
 	}
         /* Mark as function result. */
         xsltRegisterLocalRVT(ctxt, container);
-        container->psvi = XSLT_RVT_FUNC_RESULT;
+        container->compression = XSLT_RVT_FUNC_RESULT;
 
 	oldInsert = ctxt->insert;
 	ctxt->insert = (xmlNodePtr) container;
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 40ab810..19d7326 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -2276,17 +2276,17 @@ xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
     do {
         tmp = cur;
         cur = (xmlDocPtr) cur->next;
-        if (tmp->psvi == XSLT_RVT_LOCAL) {
+        if (tmp->compression == XSLT_RVT_LOCAL) {
             xsltReleaseRVT(ctxt, tmp);
-        } else if (tmp->psvi == XSLT_RVT_GLOBAL) {
+        } else if (tmp->compression == XSLT_RVT_GLOBAL) {
             xsltRegisterPersistRVT(ctxt, tmp);
-        } else if (tmp->psvi == XSLT_RVT_FUNC_RESULT) {
+        } else if (tmp->compression == XSLT_RVT_FUNC_RESULT) {
             /*
              * This will either register the RVT again or move it to the
              * context variable.
              */
             xsltRegisterLocalRVT(ctxt, tmp);
-            tmp->psvi = XSLT_RVT_FUNC_RESULT;
+            tmp->compression = XSLT_RVT_FUNC_RESULT;
         } else {
             xmlGenericError(xmlGenericErrorContext,
                     "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
diff --git a/libxslt/variables.c b/libxslt/variables.c
index 4c972a4..dab0bab 100644
--- a/libxslt/variables.c
+++ b/libxslt/variables.c
@@ -123,7 +123,7 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
 	return(-1);
 
     RVT->prev = NULL;
-    RVT->psvi = XSLT_RVT_LOCAL;
+    RVT->compression = XSLT_RVT_LOCAL;
 
     /*
     * We'll restrict the lifetime of user-created fragments
@@ -163,7 +163,7 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
 	return(-1);
 
     RVT->prev = NULL;
-    RVT->psvi = XSLT_RVT_LOCAL;
+    RVT->compression = XSLT_RVT_LOCAL;
 
     /*
     * When evaluating "select" expressions of xsl:variable
@@ -255,7 +255,7 @@ xsltExtensionInstructionResultRegister(
  * Returns 0 in case of success and -1 in case of error.
  */
 int
-xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
+xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, int val) {
     int i;
     xmlNodePtr cur;
     xmlDocPtr doc;
@@ -302,34 +302,34 @@ xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
 	    return(-1);
 	}
 	if (doc->name && (doc->name[0] == ' ') &&
-            doc->psvi != XSLT_RVT_GLOBAL) {
+            doc->compression != XSLT_RVT_GLOBAL) {
 	    /*
 	    * This is a result tree fragment.
-	    * We store ownership information in the @psvi field.
+	    * We store ownership information in the @compression field.
 	    * TODO: How do we know if this is a doc acquired via the
 	    *  document() function?
 	    */
 #ifdef WITH_XSLT_DEBUG_VARIABLE
             XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
-                "Flagging RVT %p: %p -> %p\n", doc, doc->psvi, val));
+                "Flagging RVT %p: %d -> %d\n", doc, doc->compression, val));
 #endif
 
             if (val == XSLT_RVT_LOCAL) {
-                if (doc->psvi == XSLT_RVT_FUNC_RESULT)
-                    doc->psvi = XSLT_RVT_LOCAL;
+                if (doc->compression == XSLT_RVT_FUNC_RESULT)
+                    doc->compression = XSLT_RVT_LOCAL;
             } else if (val == XSLT_RVT_GLOBAL) {
-                if (doc->psvi != XSLT_RVT_LOCAL) {
+                if (doc->compression != XSLT_RVT_LOCAL) {
 		    xmlGenericError(xmlGenericErrorContext,
-                            "xsltFlagRVTs: Invalid transition %p => GLOBAL\n",
-                            doc->psvi);
-                    doc->psvi = XSLT_RVT_GLOBAL;
+                            "xsltFlagRVTs: Invalid transition %d => GLOBAL\n",
+                            doc->compression);
+                    doc->compression = XSLT_RVT_GLOBAL;
                     return(-1);
                 }
 
                 /* Will be registered as persistant in xsltReleaseLocalRVTs. */
-                doc->psvi = XSLT_RVT_GLOBAL;
+                doc->compression = XSLT_RVT_GLOBAL;
             } else if (val == XSLT_RVT_FUNC_RESULT) {
-	        doc->psvi = val;
+	        doc->compression = val;
             }
 	}
     }
@@ -382,7 +382,7 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
 	/*
 	* Reset the ownership information.
 	*/
-	RVT->psvi = NULL;
+	RVT->compression = 0;
 
 	RVT->next = (xmlNodePtr) ctxt->cache->RVT;
 	ctxt->cache->RVT = RVT;
@@ -421,7 +421,7 @@ xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
 {
     if ((ctxt == NULL) || (RVT == NULL)) return(-1);
 
-    RVT->psvi = XSLT_RVT_GLOBAL;
+    RVT->compression = XSLT_RVT_GLOBAL;
     RVT->prev = NULL;
     RVT->next = (xmlNodePtr) ctxt->persistRVT;
     if (ctxt->persistRVT != NULL)
@@ -580,15 +580,15 @@ xsltFreeStackElem(xsltStackElemPtr elem) {
 	    cur = elem->fragment;
 	    elem->fragment = (xmlDocPtr) cur->next;
 
-            if (cur->psvi == XSLT_RVT_LOCAL) {
+            if (cur->compression == XSLT_RVT_LOCAL) {
 		xsltReleaseRVT(elem->context, cur);
-            } else if (cur->psvi == XSLT_RVT_FUNC_RESULT) {
+            } else if (cur->compression == XSLT_RVT_FUNC_RESULT) {
                 xsltRegisterLocalRVT(elem->context, cur);
-                cur->psvi = XSLT_RVT_FUNC_RESULT;
+                cur->compression = XSLT_RVT_FUNC_RESULT;
             } else {
                 xmlGenericError(xmlGenericErrorContext,
-                        "xsltFreeStackElem: Unexpected RVT flag %p\n",
-                        cur->psvi);
+                        "xsltFreeStackElem: Unexpected RVT flag %d\n",
+                        cur->compression);
             }
 	}
     }
@@ -989,7 +989,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
 		* the Result Tree Fragment.
 		*/
 		variable->fragment = container;
-                container->psvi = XSLT_RVT_LOCAL;
+                container->compression = XSLT_RVT_LOCAL;
 
 		oldOutput = ctxt->output;
 		oldInsert = ctxt->insert;
diff --git a/libxslt/variables.h b/libxslt/variables.h
index 039288f..e2adee0 100644
--- a/libxslt/variables.h
+++ b/libxslt/variables.h
@@ -43,7 +43,7 @@ extern "C" {
  *
  * RVT is destroyed after the current instructions ends.
  */
-#define XSLT_RVT_LOCAL       ((void *)1)
+#define XSLT_RVT_LOCAL       1
 
 /**
  * XSLT_RVT_FUNC_RESULT:
@@ -52,14 +52,14 @@ extern "C" {
  * destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or
  * XSLT_RVT_VARIABLE in the template that receives the return value.
  */
-#define XSLT_RVT_FUNC_RESULT ((void *)2)
+#define XSLT_RVT_FUNC_RESULT 2
 
 /**
  * XSLT_RVT_GLOBAL:
  *
  * RVT is part of a global variable.
  */
-#define XSLT_RVT_GLOBAL      ((void *)3)
+#define XSLT_RVT_GLOBAL      3
 
 /*
  * Interfaces for the variable module.
diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
index b0125c2..74a2b64 100644
--- a/libxslt/xsltInternals.h
+++ b/libxslt/xsltInternals.h
@@ -1916,7 +1916,7 @@ XSLTPUBFUN int XSLTCALL
 			xsltFlagRVTs(
 						 xsltTransformContextPtr ctxt,
 						 xmlXPathObjectPtr obj,
-						 void *val);
+						 int val);
 XSLTPUBFUN void XSLTCALL
 			xsltFreeRVTs		(xsltTransformContextPtr ctxt);
 XSLTPUBFUN void XSLTCALL
