Blame SOURCES/libxslt-1.1.32-unexpected-rvt-flag.patch

4607f9
From 7d81bd62d5788a9e2931c20a3d0a6be7e703c608 Mon Sep 17 00:00:00 2001
4607f9
From: Nick Wellnhofer <wellnhofer@aevum.de>
4607f9
Date: Mon, 23 Jul 2018 22:52:12 +0200
4607f9
Subject: [PATCH] Fix EXSLT functions returning RVTs from outer scopes
4607f9
4607f9
The RVTs referenced from function results must not be blindly registered
4607f9
as local, as they might be part of variables from an outer scope. Remove
4607f9
LOCAL/VARIABLE distinction for RVTs. Don't register as local RVT
4607f9
unconditionally when reflagging as LOCAL. Instead, register function
4607f9
result RVTs from inner variables as local RVTs when they're released in
4607f9
xsltFreeStackElem. Keep local function result RVTs xsltReleaseLocalRVTs
4607f9
instead of reregistering.
4607f9
4607f9
Closes: https://gitlab.gnome.org/GNOME/libxslt/issues/2
4607f9
4607f9
Thanks to Daniel Mendler and Martin Gieseking for the reports.
4607f9
---
4607f9
 libexslt/functions.c      | 11 ++++++++++-
4607f9
 libxslt/transform.c       | 17 ++++++++++++++---
4607f9
 libxslt/variables.c       | 27 +++++++++++----------------
4607f9
 libxslt/variables.h       | 12 ++----------
4607f9
 tests/docs/bug-210.xml    |  1 +
4607f9
 tests/docs/bug-211.xml    |  1 +
4607f9
 tests/general/bug-210.out |  2 ++
4607f9
 tests/general/bug-210.xsl | 20 ++++++++++++++++++++
4607f9
 tests/general/bug-211.out |  2 ++
4607f9
 tests/general/bug-211.xsl | 26 ++++++++++++++++++++++++++
4607f9
 10 files changed, 89 insertions(+), 30 deletions(-)
4607f9
 create mode 100644 tests/docs/bug-210.xml
4607f9
 create mode 100644 tests/docs/bug-211.xml
4607f9
 create mode 100644 tests/general/bug-210.out
4607f9
 create mode 100644 tests/general/bug-210.xsl
4607f9
 create mode 100644 tests/general/bug-211.out
4607f9
 create mode 100644 tests/general/bug-211.xsl
4607f9
4607f9
diff --git a/libexslt/functions.c b/libexslt/functions.c
4607f9
index 2b83ca34..b7b968f8 100644
4607f9
--- a/libexslt/functions.c
4607f9
+++ b/libexslt/functions.c
4607f9
@@ -426,7 +426,15 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
4607f9
 	}
4607f9
     }
4607f9
     /*
4607f9
-     * actual processing
4607f9
+     * Actual processing. Note that contextVariable is set to NULL which
4607f9
+     * means that RVTs returned from functions always end up as local RVTs,
4607f9
+     * not as variable fragments if the function is called in the select
4607f9
+     * expression of an xsl:variable. This is a hack that only works because
4607f9
+     * xsltReleaseLocalRVTs isn't called after processing xsl:variable.
4607f9
+     *
4607f9
+     * It would probably be better to remove the fragile contextVariable
4607f9
+     * logic and make xsltEvalVariable move the required RVTs into the
4607f9
+     * variable manually.
4607f9
      */
4607f9
     fake = xmlNewDocNode(tctxt->output, NULL,
4607f9
 			 (const xmlChar *)"fake", NULL);
4607f9
@@ -766,6 +774,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
4607f9
 	    return;
4607f9
 	}
4607f9
         /* Mark as function result. */
4607f9
+        xsltRegisterLocalRVT(ctxt, container);
4607f9
         container->psvi = XSLT_RVT_FUNC_RESULT;
4607f9
 
4607f9
 	oldInsert = ctxt->insert;
4607f9
diff --git a/libxslt/transform.c b/libxslt/transform.c
4607f9
index 90d2731d..d7af31f1 100644
4607f9
--- a/libxslt/transform.c
4607f9
+++ b/libxslt/transform.c
4607f9
@@ -2295,6 +2295,7 @@ static void
4607f9
 xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
4607f9
 {
4607f9
     xmlDocPtr cur = ctxt->localRVT, tmp;
4607f9
+    xmlDocPtr prev = NULL;
4607f9
 
4607f9
     if (cur == base)
4607f9
         return;
4607f9
@@ -2308,16 +2309,26 @@ xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
4607f9
             xsltReleaseRVT(ctxt, tmp);
4607f9
         } else if (tmp->psvi == XSLT_RVT_GLOBAL) {
4607f9
             xsltRegisterPersistRVT(ctxt, tmp);
4607f9
-        } else if (tmp->psvi != XSLT_RVT_FUNC_RESULT) {
4607f9
+        } else if (tmp->psvi == XSLT_RVT_FUNC_RESULT) {
4607f9
+            if (prev == NULL)
4607f9
+                ctxt->localRVT = tmp;
4607f9
+            else
4607f9
+                prev->next = (xmlNodePtr) tmp;
4607f9
+            tmp->prev = (xmlNodePtr) prev;
4607f9
+            prev = tmp;
4607f9
+        } else {
4607f9
             xmlGenericError(xmlGenericErrorContext,
4607f9
                     "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
4607f9
                     tmp->psvi);
4607f9
         }
4607f9
     } while (cur != base);
4607f9
 
4607f9
+    if (prev == NULL)
4607f9
+        ctxt->localRVT = base;
4607f9
+    else
4607f9
+        prev->next = (xmlNodePtr) base;
4607f9
     if (base != NULL)
4607f9
-        base->prev = NULL;
4607f9
-    ctxt->localRVT = base;
4607f9
+        base->prev = (xmlNodePtr) prev;
4607f9
 }
4607f9
 
4607f9
 /**
4607f9
diff --git a/libxslt/variables.c b/libxslt/variables.c
4607f9
index fe6f299c..8f88e573 100644
4607f9
--- a/libxslt/variables.c
4607f9
+++ b/libxslt/variables.c
4607f9
@@ -123,7 +123,7 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
4607f9
 	return(-1);
4607f9
 
4607f9
     RVT->prev = NULL;
4607f9
-    RVT->psvi = XSLT_RVT_VARIABLE;
4607f9
+    RVT->psvi = XSLT_RVT_LOCAL;
4607f9
 
4607f9
     /*
4607f9
     * We'll restrict the lifetime of user-created fragments
4607f9
@@ -163,6 +163,7 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
4607f9
 	return(-1);
4607f9
 
4607f9
     RVT->prev = NULL;
4607f9
+    RVT->psvi = XSLT_RVT_LOCAL;
4607f9
 
4607f9
     /*
4607f9
     * When evaluating "select" expressions of xsl:variable
4607f9
@@ -173,7 +174,6 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
4607f9
     if ((ctxt->contextVariable != NULL) &&
4607f9
 	(XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))
4607f9
     {
4607f9
-        RVT->psvi = XSLT_RVT_VARIABLE;
4607f9
 	RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
4607f9
 	XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
4607f9
 	return(0);
4607f9
@@ -183,7 +183,6 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
4607f9
     * If not reference by a returning instruction (like EXSLT's function),
4607f9
     * then this fragment will be freed, when the instruction exits.
4607f9
     */
4607f9
-    RVT->psvi = XSLT_RVT_LOCAL;
4607f9
     RVT->next = (xmlNodePtr) ctxt->localRVT;
4607f9
     if (ctxt->localRVT != NULL)
4607f9
 	ctxt->localRVT->prev = (xmlNodePtr) RVT;
4607f9
@@ -314,14 +313,8 @@ xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
4607f9
 #endif
4607f9
 
4607f9
             if (val == XSLT_RVT_LOCAL) {
4607f9
-                if (doc->psvi != XSLT_RVT_FUNC_RESULT) {
4607f9
-		    xmlGenericError(xmlGenericErrorContext,
4607f9
-                            "xsltFlagRVTs: Invalid transition %p => LOCAL\n",
4607f9
-                            doc->psvi);
4607f9
-                    return(-1);
4607f9
-                }
4607f9
-
4607f9
-                xsltRegisterLocalRVT(ctxt, doc);
4607f9
+                if (doc->psvi == XSLT_RVT_FUNC_RESULT)
4607f9
+                    doc->psvi = XSLT_RVT_LOCAL;
4607f9
             } else if (val == XSLT_RVT_GLOBAL) {
4607f9
                 if (doc->psvi != XSLT_RVT_LOCAL) {
4607f9
 		    xmlGenericError(xmlGenericErrorContext,
4607f9
@@ -585,10 +578,12 @@ xsltFreeStackElem(xsltStackElemPtr elem) {
4607f9
 	    cur = elem->fragment;
4607f9
 	    elem->fragment = (xmlDocPtr) cur->next;
4607f9
 
4607f9
-            if (cur->psvi == XSLT_RVT_VARIABLE) {
4607f9
-		xsltReleaseRVT((xsltTransformContextPtr) elem->context,
4607f9
-		    cur);
4607f9
-            } else if (cur->psvi != XSLT_RVT_FUNC_RESULT) {
4607f9
+            if (cur->psvi == XSLT_RVT_LOCAL) {
4607f9
+		xsltReleaseRVT(elem->context, cur);
4607f9
+            } else if (cur->psvi == XSLT_RVT_FUNC_RESULT) {
4607f9
+                xsltRegisterLocalRVT(elem->context, cur);
4607f9
+                cur->psvi = XSLT_RVT_FUNC_RESULT;
4607f9
+            } else {
4607f9
                 xmlGenericError(xmlGenericErrorContext,
4607f9
                         "xsltFreeStackElem: Unexpected RVT flag %p\n",
4607f9
                         cur->psvi);
4607f9
@@ -992,7 +987,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
4607f9
 		* the Result Tree Fragment.
4607f9
 		*/
4607f9
 		variable->fragment = container;
4607f9
-                container->psvi = XSLT_RVT_VARIABLE;
4607f9
+                container->psvi = XSLT_RVT_LOCAL;
4607f9
 
4607f9
 		oldOutput = ctxt->output;
4607f9
 		oldInsert = ctxt->insert;
4607f9
diff --git a/libxslt/variables.h b/libxslt/variables.h
4607f9
index 24acf8d1..039288fb 100644
4607f9
--- a/libxslt/variables.h
4607f9
+++ b/libxslt/variables.h
4607f9
@@ -45,14 +45,6 @@ extern "C" {
4607f9
  */
4607f9
 #define XSLT_RVT_LOCAL       ((void *)1)
4607f9
 
4607f9
-/**
4607f9
- * XSLT_RVT_VARIABLE:
4607f9
- *
4607f9
- * RVT is part of a local variable and destroyed after the variable goes out
4607f9
- * of scope.
4607f9
- */
4607f9
-#define XSLT_RVT_VARIABLE    ((void *)2)
4607f9
-
4607f9
 /**
4607f9
  * XSLT_RVT_FUNC_RESULT:
4607f9
  *
4607f9
@@ -60,14 +52,14 @@ extern "C" {
4607f9
  * destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or
4607f9
  * XSLT_RVT_VARIABLE in the template that receives the return value.
4607f9
  */
4607f9
-#define XSLT_RVT_FUNC_RESULT ((void *)3)
4607f9
+#define XSLT_RVT_FUNC_RESULT ((void *)2)
4607f9
 
4607f9
 /**
4607f9
  * XSLT_RVT_GLOBAL:
4607f9
  *
4607f9
  * RVT is part of a global variable.
4607f9
  */
4607f9
-#define XSLT_RVT_GLOBAL      ((void *)4)
4607f9
+#define XSLT_RVT_GLOBAL      ((void *)3)
4607f9
 
4607f9
 /*
4607f9
  * Interfaces for the variable module.
4607f9
diff --git a/tests/docs/bug-210.xml b/tests/docs/bug-210.xml
4607f9
new file mode 100644
4607f9
index 00000000..69d62f2c
4607f9
--- /dev/null
4607f9
+++ b/tests/docs/bug-210.xml
4607f9
@@ -0,0 +1 @@
4607f9
+<doc/>
4607f9
diff --git a/tests/docs/bug-211.xml b/tests/docs/bug-211.xml
4607f9
new file mode 100644
4607f9
index 00000000..69d62f2c
4607f9
--- /dev/null
4607f9
+++ b/tests/docs/bug-211.xml
4607f9
@@ -0,0 +1 @@
4607f9
+<doc/>
4607f9
diff --git a/tests/general/bug-210.out b/tests/general/bug-210.out
4607f9
new file mode 100644
4607f9
index 00000000..445906d6
4607f9
--- /dev/null
4607f9
+++ b/tests/general/bug-210.out
4607f9
@@ -0,0 +1,2 @@
4607f9
+
4607f9
+value
4607f9
diff --git a/tests/general/bug-210.xsl b/tests/general/bug-210.xsl
4607f9
new file mode 100644
4607f9
index 00000000..1915171d
4607f9
--- /dev/null
4607f9
+++ b/tests/general/bug-210.xsl
4607f9
@@ -0,0 +1,20 @@
4607f9
+
4607f9
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4607f9
+    xmlns:exsl="http://exslt.org/common"
4607f9
+    xmlns:func="http://exslt.org/functions"
4607f9
+    xmlns:my="my-namespace"
4607f9
+    extension-element-prefixes="exsl func">
4607f9
+
4607f9
+<xsl:template match="/">
4607f9
+    <xsl:variable name="var">
4607f9
+        value
4607f9
+    </xsl:variable>
4607f9
+    <xsl:copy-of select="my:func($var)"/>
4607f9
+</xsl:template>
4607f9
+
4607f9
+<func:function name="my:func">
4607f9
+    <xsl:param name="var"/>
4607f9
+    <func:result select="$var"/>
4607f9
+</func:function>
4607f9
+
4607f9
+</xsl:stylesheet>
4607f9
diff --git a/tests/general/bug-211.out b/tests/general/bug-211.out
4607f9
new file mode 100644
4607f9
index 00000000..7b3cf11c
4607f9
--- /dev/null
4607f9
+++ b/tests/general/bug-211.out
4607f9
@@ -0,0 +1,2 @@
4607f9
+
4607f9
+__
4607f9
diff --git a/tests/general/bug-211.xsl b/tests/general/bug-211.xsl
4607f9
new file mode 100644
4607f9
index 00000000..557f5fb3
4607f9
--- /dev/null
4607f9
+++ b/tests/general/bug-211.xsl
4607f9
@@ -0,0 +1,26 @@
4607f9
+
4607f9
+
4607f9
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4607f9
+                xmlns:str="http://exslt.org/strings"
4607f9
+                xmlns:fn="http://exslt.org/functions"
4607f9
+                xmlns:adoc="http://asciidoc.org/"
4607f9
+                extension-element-prefixes="fn">
4607f9
+
4607f9
+  <fn:function name="adoc:sanitize">
4607f9
+    <xsl:param name="id"/>
4607f9
+    <xsl:variable name="tmp" select="str:replace($id, '__', '_')"/>
4607f9
+    <xsl:choose>
4607f9
+      <xsl:when test="contains($tmp, '__')">
4607f9
+        <fn:result select="adoc:sanitize($tmp)"/>
4607f9
+      </xsl:when>
4607f9
+      <xsl:otherwise>
4607f9
+        <fn:result select="$id"/>
4607f9
+      </xsl:otherwise>
4607f9
+    </xsl:choose>
4607f9
+  </fn:function>
4607f9
+
4607f9
+  <xsl:template match="*">
4607f9
+    <xsl:value-of select="adoc:sanitize('________')"/>
4607f9
+  </xsl:template>
4607f9
+
4607f9
+</xsl:stylesheet>
4607f9
-- 
4607f9
GitLab
4607f9