GNOME Bugzilla – Bug 328218
Already freed chunk warning from accessing union'd node-set('text')s
Last modified: 2006-07-14 16:21:05 UTC
Please describe the problem: A warning is thrown about an already free chunk. I imagine this is pointing at a bug somewhere. See "How To Reproduce", to, uh, reproduce it. =) (I wasn't sure what I'd get from this xslt code, and thus my testing.) Steps to reproduce: <?xml version="1.0" encoding="utf-8"?> <transform version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:xl="http://www.w3.org/1999/xlink" xmlns:set="http://exslt.org/sets" xmlns:exsl="http://exslt.org/common" xmlns:func="http://exslt.org/functions" xmlns:ds="http://jwp.name/xml/ds" extension-element-prefixes="func" > <template match="/"> <variable name="foo" select="exsl:node-set('foo')|exsl:node-set('bar')"/> <message><value-of select="$foo/text()[position()=first()]"/></message> <message><value-of select="$foo/text()[position()=last()]"/></message> </template> </transform> Actual results: It gives a warning about an already free chunk of memory: xsltproc in free(): warning: chunk is already free xsltproc in free(): warning: chunk is already free Expected results: Not get warnings. Does this happen every time? Yes. Other information: $ xsltproc --version Using libxml 20622, libxslt 10115 and libexslt 812 xsltproc was compiled against libxml 20622, libxslt 10115 and libexslt 812 libxslt 10115 was compiled against libxml 20622 libexslt 812 was compiled against libxml 20622 $ uname -a FreeBSD lit 6.0-STABLE FreeBSD 6.0-STABLE #1: Sat Dec 31 23:42:00 MST 2005 root@lit:/usr/obj/usr/src/sys/void i386 This xsltproc comes from FreeBSD's precompiled libxslt package(built from their port system).
This is a bug. In exsltNodeSetFunction() (libexslt/common.c) a tree fragment is created with xmlXPathNewValueTree(), containing a single text node (without a doc). There are two errors here: 1) there's no tree fragment (an xmlDoc in Libxml2) 2) the @boolval of the XPath object is not reset to 0; this means that the XPath module will free the text node, when the XPath object is freed. Due to 2), and the fact that the two text nodes "foo" and "bar" are unioned with xmlXPathNodeSetMerge(), creates a scenario where a text node is exitent in two node sets: the first is an XSLT tree fragment, the second a normal node set. Somewhere in the machinery the XPath object, which reflects the tree fragment is freed and with it the text node. The node set, which was the result of the node set merge, is still accessible and contains a reference to this already freed text node. How to fix: 1) Create a tree fragment for the text nodes with xsltCreateRVT() and register it locally with xsltRegisterLocalRVT(). Add the text node to the fragment. 2) Use xmlXPathNewNodeSet() to store the text node in a node set; this will prevent it from being freed by the XPath module. I applied this fix to my local code and it works fine, except for the fact that it still crashes, since my new tree fragment garbage collecting mechanism will free the tree fragments too early. So in the case of tree fragments created during the evaluation of and xsl:variable and xsl:param we need to bing the fragments to the scope of the xsl:variable or xsl:param.
The corrected test case: <?xml version="1.0"?> <transform version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common"> <template match="/"> <variable name="foo" select="exsl:node-set('foo') | exsl:node-set('bar')"/> <copy-of select="$foo[position() = 1]"/> <copy-of select="$foo[position() = 2]"/> </template> </transform>
Fixed in CVS. Thanks for the report!