Use-after-free in libxml2 2.9.10 and below
I've encountered a sporadic crash in our build that I minimized to the following test case (minimized from a docbook source/stylesheet):
s5-1.xml
<?xml version="1.0"?>
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<para>
<xref/>
</para>
<para>
<xi:include href="s5-2.xml"><xi:fallback/></xi:include>
</para>
</book>
s5-2.xml
<?xml version="1.0"?>
<para/>
s5.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
<xsl:key name="id" match="*" use="@id"/>
<xsl:key name="gid" match="*" use="generate-id()"/>
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="xref" name="xref">
<xsl:param name="xlink.targets" select="key('id','')"/>
</xsl:template>
</xsl:stylesheet>
Running it with:
valgrind --num-callers=50 xsltproc -o /dev/null --xinclude s5.xsl s5-1.xml
produces the following error report:
==1054933== Invalid read of size 4
==1054933== at 0x5797806: xmlXPathFreeNodeSet (xpath.c:4185)
==1054933== by 0x576D9A4: xmlHashFree (hash.c:339)
==1054933== by 0x4E4E784: xsltFreeKeyTable (keys.c:162)
==1054933== by 0x4E4E784: xsltFreeKeyTableList (keys.c:181)
==1054933== by 0x4E4E784: xsltFreeDocumentKeys (keys.c:932)
==1054933== by 0x4E573C9: xsltFreeDocuments (documents.c:258)
==1054933== by 0x4E5C90B: xsltFreeTransformContext (transform.c:652)
==1054933== by 0x403302: xsltProcess (xsltproc.c:492)
==1054933== by 0x402AC1: main (xsltproc.c:888)
==1054933== Address 0x69e2748 is 8 bytes inside a block of size 120 free'd
==1054933== at 0x4C28CDD: free (vg_replace_malloc.c:530)
==1054933== by 0x5764F77: xmlFreeNodeList (tree.c:3684)
==1054933== by 0x576532B: xmlFreeNode (tree.c:3729)
==1054933== by 0x4E5F0C6: xsltApplyTemplates (transform.c:5012)
==1054933== by 0x4E5AFB2: xsltApplySequenceConstructor (transform.c:2649)
==1054933== by 0x4E5DBB1: xsltApplyXSLTTemplate (transform.c:3110)
==1054933== by 0x4E5E1F3: xsltProcessOneNode (transform.c:2099)
==1054933== by 0x4E5EF10: xsltApplyTemplates (transform.c:5144)
==1054933== by 0x4E5AFB2: xsltApplySequenceConstructor (transform.c:2649)
==1054933== by 0x4E5DBB1: xsltApplyXSLTTemplate (transform.c:3110)
==1054933== by 0x4E5E1F3: xsltProcessOneNode (transform.c:2099)
==1054933== by 0x4E5E7CE: xsltDefaultProcessOneNode (transform.c:1929)
==1054933== by 0x4E5E7CE: xsltProcessOneNode (transform.c:2061)
==1054933== by 0x4E613DE: xsltApplyStylesheetInternal (transform.c:6162)
==1054933== by 0x4E61A70: xsltRunStylesheetUser (transform.c:6452)
==1054933== by 0x4032D9: xsltProcess (xsltproc.c:483)
==1054933== by 0x402AC1: main (xsltproc.c:888)
==1054933== Block was alloc'd at
==1054933== at 0x4C27BE3: malloc (vg_replace_malloc.c:299)
==1054933== by 0x5763542: xmlNewNodeEatName (tree.c:2266)
==1054933== by 0x576764D: xmlNewDocNodeEatName (tree.c:2341)
==1054933== by 0x5810F8A: xmlSAX2StartElementNs (SAX2.c:2263)
==1054933== by 0x57568CF: xmlParseStartTag2 (parser.c:9752)
==1054933== by 0x575B1E3: xmlParseElement (parser.c:10127)
==1054933== by 0x575A9D7: xmlParseContent (parser.c:10040)
==1054933== by 0x575B282: xmlParseElement (parser.c:10213)
==1054933== by 0x575A9D7: xmlParseContent (parser.c:10040)
==1054933== by 0x575B282: xmlParseElement (parser.c:10213)
==1054933== by 0x575A9D7: xmlParseContent (parser.c:10040)
==1054933== by 0x575B282: xmlParseElement (parser.c:10213)
==1054933== by 0x575B9F9: xmlParseDocument (parser.c:10904)
==1054933== by 0x575BCE6: xmlDoRead (parser.c:15379)
==1054933== by 0x402AF4: main (xsltproc.c:880)
The issue is no longer reproducible after the commit 1abf2967; however, that commit only mentions some performance enhancement as the goal of the change. Also, it is somewhat strange that the issue only reproduces if the (otherwise unused xsl:key named gid
is defined). I wonder if that commit was a true fix for this issue or if it just changed some code paths that the particular test case no longer manifests the issue (but the invalid read remains, just now pointing to an allocated memory block).
I'd appreciate a review of that fix and the test case by the maintainers to check if this issue needs to be debugged further.