Commit 08b62c25 authored by Nick Wellnhofer's avatar Nick Wellnhofer

Always set context node before calling XPath iterators

The xmlXPathNext* iterators rely on the XPath context node being set to
the start node of the iteration. Some parts of the code base like the
xsl:key functions also leave the context node in an unspecified state.
Make sure that the context node is reset before invoking the XPath
iterators. Also backup and restore the context node in
xsltNumberFormatGetMultipleLevel for good measure.

This bug could also lead to type confusion and invalid reads in
connection with namespace nodes.

Fixes #13. Also see the Chromium bug report:

https://bugs.chromium.org/p/chromium/issues/detail?id=930663

Thanks to Nicolas Grégoire for the report.
parent 19c1ea58
......@@ -646,42 +646,51 @@ xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
{
int amount = 0;
int cnt;
xmlNodePtr oldCtxtNode;
xmlNodePtr ancestor;
xmlNodePtr preceding;
xmlXPathParserContextPtr parser;
context->xpathCtxt->node = node;
oldCtxtNode = context->xpathCtxt->node;
parser = xmlXPathNewParserContext(NULL, context->xpathCtxt);
if (parser) {
/* ancestor-or-self::*[count] */
for (ancestor = node;
(ancestor != NULL) && (ancestor->type != XML_DOCUMENT_NODE);
ancestor = xmlXPathNextAncestor(parser, ancestor)) {
ancestor = node;
while ((ancestor != NULL) && (ancestor->type != XML_DOCUMENT_NODE)) {
if ((fromPat != NULL) &&
xsltTestCompMatchList(context, ancestor, fromPat))
break; /* for */
/*
* The xmlXPathNext* iterators require that the context node is
* set to the start node. Calls to xsltTestCompMatch* may also
* leave the context node in an undefined state, so make sure
* that the context node is reset before each iterator invocation.
*/
if (xsltTestCompMatchCount(context, ancestor, countPat, node)) {
/* count(preceding-sibling::*) */
cnt = 1;
for (preceding =
xmlXPathNextPrecedingSibling(parser, ancestor);
preceding != NULL;
preceding =
xmlXPathNextPrecedingSibling(parser, preceding)) {
context->xpathCtxt->node = ancestor;
preceding = xmlXPathNextPrecedingSibling(parser, ancestor);
while (preceding != NULL) {
if (xsltTestCompMatchCount(context, preceding, countPat,
node))
cnt++;
context->xpathCtxt->node = ancestor;
preceding =
xmlXPathNextPrecedingSibling(parser, preceding);
}
array[amount++] = (double)cnt;
if (amount >= max)
break; /* for */
}
context->xpathCtxt->node = node;
ancestor = xmlXPathNextAncestor(parser, ancestor);
}
xmlXPathFreeParserContext(parser);
}
context->xpathCtxt->node = oldCtxtNode;
return amount;
}
......
<top xmlns:ns1="foo"/>
<?xml version="1.0"?>
1
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="aaa" match="/bbb" use="./ccc"/>
<xsl:template match="*">
<xsl:for-each select="namespace::*[position()=2]">
<xsl:number from="key('e','f')"/>
</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