Commit d182d8f6 authored by Nick Wellnhofer's avatar Nick Wellnhofer

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.
parent fc1ff481
...@@ -531,6 +531,43 @@ xsltNumberFormatInsertNumbers(xsltNumberDataPtr data, ...@@ -531,6 +531,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 static int
xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
xmlNodePtr node, xmlNodePtr node,
...@@ -562,21 +599,8 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, ...@@ -562,21 +599,8 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
while (cur != NULL) { while (cur != NULL) {
/* process current node */ /* process current node */
if (countPat == NULL) { if (xsltTestCompMatchCount(context, cur, countPat, node))
if ((node->type == cur->type) && cnt++;
/* 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 ((fromPat != NULL) && if ((fromPat != NULL) &&
xsltTestCompMatchList(context, cur, fromPat)) { xsltTestCompMatchList(context, cur, fromPat)) {
break; /* while */ break; /* while */
...@@ -633,30 +657,18 @@ xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context, ...@@ -633,30 +657,18 @@ xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
xsltTestCompMatchList(context, ancestor, fromPat)) xsltTestCompMatchList(context, ancestor, fromPat))
break; /* for */ break; /* for */
if ((countPat == NULL && node->type == ancestor->type && if (xsltTestCompMatchCount(context, ancestor, countPat, node)) {
xmlStrEqual(node->name, ancestor->name)) ||
xsltTestCompMatchList(context, ancestor, countPat)) {
/* count(preceding-sibling::*) */ /* count(preceding-sibling::*) */
cnt = 0; cnt = 1;
for (preceding = ancestor; for (preceding =
xmlXPathNextPrecedingSibling(parser, ancestor);
preceding != NULL; preceding != NULL;
preceding = preceding =
xmlXPathNextPrecedingSibling(parser, preceding)) { xmlXPathNextPrecedingSibling(parser, preceding)) {
if (countPat == NULL) {
if ((preceding->type == ancestor->type) && if (xsltTestCompMatchCount(context, preceding, countPat,
xmlStrEqual(preceding->name, ancestor->name)){ node))
if ((preceding->ns == ancestor->ns) || cnt++;
((preceding->ns != NULL) &&
(ancestor->ns != NULL) &&
(xmlStrEqual(preceding->ns->href,
ancestor->ns->href) )))
cnt++;
}
} else {
if (xsltTestCompMatchList(context, preceding,
countPat))
cnt++;
}
} }
array[amount++] = (double)cnt; array[amount++] = (double)cnt;
if (amount >= max) if (amount >= max)
......
<top xmlns:a="AAAA" xmlns:b="BBBB" xmlns:c="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC">
<foo/>
<bar/>
</top>
<?xml version="1.0"?>
1111
1111
<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>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment