[libxslt] Don't cache direct evaluation of patterns with variables



commit a846514a159a2524266b57d8aae47b66572d0b0a
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Wed Nov 21 17:12:17 2018 +0100

    Don't cache direct evaluation of patterns with variables
    
    The slow pattern matching path in xsltTestCompMatchDirect caches the
    result of evaluating the pattern. But this can't be done if the pattern
    contains variables which could evaluate to different values.
    
    Only enable the cache for patterns like template matches that don't
    allow variable references. Don't use the cache for "count" and "from"
    patterns in xsl:number.
    
    A more fine-grained approach would be nice, but most effort should be
    spent on eliminating the slow path completely.
    
    Thanks to Martin Honnen for the report.
    
    Fixes #6.

 libxslt/pattern.c         |  5 ++++-
 tests/docs/bug-214.xml    |  6 ++++++
 tests/general/bug-214.out |  6 ++++++
 tests/general/bug-214.xsl | 25 +++++++++++++++++++++++++
 4 files changed, 41 insertions(+), 1 deletion(-)
---
diff --git a/libxslt/pattern.c b/libxslt/pattern.c
index 07f11f9b..7d660192 100644
--- a/libxslt/pattern.c
+++ b/libxslt/pattern.c
@@ -113,6 +113,7 @@ struct _xsltCompMatch {
     xmlNsPtr *nsList;          /* the namespaces in scope */
     int nsNr;                  /* the number of namespaces in scope */
     xsltStepOpPtr steps;        /* ops for computation */
+    int novar;                  /* doesn't contain variables */
 };
 
 typedef struct _xsltParserContext xsltParserContext;
@@ -594,7 +595,8 @@ xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
        }
        ix = 0;
 
-       if ((parent == NULL) || (node->doc == NULL) || isRVT)
+       if ((parent == NULL) || (node->doc == NULL) || isRVT ||
+            (comp->novar == 0))
            nocache = 1;
 
        if (nocache == 0) {
@@ -1970,6 +1972,7 @@ xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc,
                j++;
        }
        element->nsNr = j;
+        element->novar = novar;
 
 
 #ifdef WITH_XSLT_DEBUG_PATTERN
diff --git a/tests/docs/bug-214.xml b/tests/docs/bug-214.xml
new file mode 100644
index 00000000..196b8025
--- /dev/null
+++ b/tests/docs/bug-214.xml
@@ -0,0 +1,6 @@
+<root>
+    <element type="a"/>
+    <element type="b"/>
+    <element type="a"/>
+</root>
+
diff --git a/tests/general/bug-214.out b/tests/general/bug-214.out
new file mode 100644
index 00000000..e51e7097
--- /dev/null
+++ b/tests/general/bug-214.out
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<root>
+    <element type="a" pos="1"/>
+    <element type="b" pos="1"/>
+    <element type="a" pos="2"/>
+</root>
diff --git a/tests/general/bug-214.xsl b/tests/general/bug-214.xsl
new file mode 100644
index 00000000..52243113
--- /dev/null
+++ b/tests/general/bug-214.xsl
@@ -0,0 +1,25 @@
+<xsl:stylesheet
+       xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
+       version="1.0">
+
+  <xsl:template match="@* | node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@* | node()"/>
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="*[@type]">
+      <xsl:copy>
+          <xsl:variable name="type" select="@type"/>
+          <xsl:variable name="pos">
+              <xsl:number count="node()[@type = $type]"/>
+          </xsl:variable>
+          <xsl:apply-templates select="@*"/>
+          <xsl:attribute name="pos">
+              <xsl:value-of select="$pos"/>
+          </xsl:attribute>
+          <xsl:apply-templates/>
+      </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]