[libxslt] Fix xsltNumberFormatGetMultipleLevel



commit d182d8f6ba3071503d96ce17395c9d55871f0242
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Tue Mar 22 18:20:01 2016 +0100

    Fix xsltNumberFormatGetMultipleLevel
    
    Namespace nodes are actually an xmlNs, not an xmlNode. They must be
    special-cased in xsltNumberFormatGetMultipleLevel to avoid an
    out-of-bounds heap access.
    
    Move the test whether a node matches the "count" pattern to a separate
    function to make the code more readable. As a side effect, we also
    compare expanded names when walking up the ancestor axis, fixing an
    insignificant bug.

 libxslt/numbers.c         |   82 +++++++++++++++++++++++++-------------------
 tests/docs/bug-186.xml    |    4 ++
 tests/general/bug-186.out |    5 +++
 tests/general/bug-186.xsl |    7 ++++
 4 files changed, 63 insertions(+), 35 deletions(-)
---
diff --git a/libxslt/numbers.c b/libxslt/numbers.c
index e3209e0..184ee6f 100644
--- a/libxslt/numbers.c
+++ b/libxslt/numbers.c
@@ -532,6 +532,43 @@ xsltNumberFormatInsertNumbers(xsltNumberDataPtr data,
 }
 
 static int
+xsltTestCompMatchCount(xsltTransformContextPtr context,
+                       xmlNodePtr node,
+                       xsltCompMatchPtr countPat,
+                       xmlNodePtr cur)
+{
+    if (countPat != NULL) {
+        return xsltTestCompMatchList(context, node, countPat);
+    }
+    else {
+        /*
+         * 7.7 Numbering
+         *
+         * If count attribute is not specified, then it defaults to the
+         * pattern that matches any node with the same node type as the
+         * current node and, if the current node has an expanded-name, with
+         * the same expanded-name as the current node.
+         */
+        if (node->type != cur->type)
+            return 0;
+        if (node->type == XML_NAMESPACE_DECL)
+            /*
+             * Namespace nodes have no preceding siblings and no parents
+             * that are namespace nodes. This means that node == cur.
+             */
+            return 1;
+        /* TODO: Skip node types without expanded names like text nodes. */
+        if (!xmlStrEqual(node->name, cur->name))
+            return 0;
+        if (node->ns == cur->ns)
+            return 1;
+        if ((node->ns == NULL) || (cur->ns == NULL))
+            return 0;
+        return (xmlStrEqual(node->ns->href, cur->ns->href));
+    }
+}
+
+static int
 xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
                            xmlNodePtr node,
                            xsltCompMatchPtr countPat,
@@ -562,21 +599,8 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
 
     while (cur != NULL) {
        /* process current node */
-       if (countPat == NULL) {
-           if ((node->type == cur->type) &&
-               /* FIXME: must use expanded-name instead of local name */
-               xmlStrEqual(node->name, cur->name)) {
-                   if ((node->ns == cur->ns) ||
-                       ((node->ns != NULL) &&
-                        (cur->ns != NULL) &&
-                        (xmlStrEqual(node->ns->href,
-                            cur->ns->href) )))
-                       cnt++;
-           }
-       } else {
-           if (xsltTestCompMatchList(context, cur, countPat))
-               cnt++;
-       }
+       if (xsltTestCompMatchCount(context, cur, countPat, node))
+           cnt++;
        if ((fromPat != NULL) &&
            xsltTestCompMatchList(context, cur, fromPat)) {
            break; /* while */
@@ -633,30 +657,18 @@ xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
                xsltTestCompMatchList(context, ancestor, fromPat))
                break; /* for */
 
-           if ((countPat == NULL && node->type == ancestor->type &&
-               xmlStrEqual(node->name, ancestor->name)) ||
-               xsltTestCompMatchList(context, ancestor, countPat)) {
+           if (xsltTestCompMatchCount(context, ancestor, countPat, node)) {
                /* count(preceding-sibling::*) */
-               cnt = 0;
-               for (preceding = ancestor;
+               cnt = 1;
+               for (preceding =
+                        xmlXPathNextPrecedingSibling(parser, ancestor);
                     preceding != NULL;
                     preceding =
                        xmlXPathNextPrecedingSibling(parser, preceding)) {
-                   if (countPat == NULL) {
-                       if ((preceding->type == ancestor->type) &&
-                           xmlStrEqual(preceding->name, ancestor->name)){
-                           if ((preceding->ns == ancestor->ns) ||
-                               ((preceding->ns != NULL) &&
-                                (ancestor->ns != NULL) &&
-                                (xmlStrEqual(preceding->ns->href,
-                                    ancestor->ns->href) )))
-                               cnt++;
-                       }
-                   } else {
-                       if (xsltTestCompMatchList(context, preceding,
-                                                 countPat))
-                           cnt++;
-                   }
+
+                   if (xsltTestCompMatchCount(context, preceding, countPat,
+                                               node))
+                       cnt++;
                }
                array[amount++] = (double)cnt;
                if (amount >= max)
diff --git a/tests/docs/bug-186.xml b/tests/docs/bug-186.xml
new file mode 100644
index 0000000..424db6b
--- /dev/null
+++ b/tests/docs/bug-186.xml
@@ -0,0 +1,4 @@
+<top xmlns:a="AAAA" xmlns:b="BBBB" xmlns:c="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC">
+<foo/>
+<bar/>
+</top>
diff --git a/tests/general/bug-186.out b/tests/general/bug-186.out
new file mode 100644
index 0000000..01a59f8
--- /dev/null
+++ b/tests/general/bug-186.out
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+
+1111
+1111
+
diff --git a/tests/general/bug-186.xsl b/tests/general/bug-186.xsl
new file mode 100644
index 0000000..9c491dd
--- /dev/null
+++ b/tests/general/bug-186.xsl
@@ -0,0 +1,7 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
+ <xsl:template match="*/*">
+  <xsl:for-each select="namespace::*">
+   <xsl:number/>
+  </xsl:for-each>
+ </xsl:template>
+</xsl:stylesheet>


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