[xml] segfault and a possible fix in parser.c



Hi Daniel, All,

I was hunting down why XML::LibXML Perl-binding fails to pass it's test-suit 
(with many segfaults) when linked to a recent release of libxml2 when I came 
to the following:

in xmlParseBalancedChunkMemoryRecover a new document and a parser context are 
temporarily created (and freed at the end of that routine). The parser ctxt 
has a dict, which is also used as the newDoc's dict at line parse.c:11196 
(CVS).

    newDoc->dict = ctxt->dict; 
    xmlDictReference(newDoc->dict);

Thus e.g. all element names of the parsed chunk are stored in this dictionary. 
But finally, both the parser ctxt and newDoc are destroyed and so is the 
dictionary. Thus, the resulting nodelist has invalid pointers in nodes' 
names. I guess, those two lines got there by mistake (we need the strings in 
the parsed chunk to exist even after the newDoc and ctxt are freed). At 
least, removing them fixes the segfaults :-) 

Below is a simple test-case I used. It doesn't segfault by itself on my box, 
but valgrind --tool=memcheck clearly identifies the problem as shown below:

==7383== Invalid read of size 4
==7383==    at 0x1B96EADB: xmlFreeNodeList__internal_alias (tree.c:3343)
==7383==    by 0x804866A: main (parse2.c:14)
==7383==  Address 0x1BBD64B8 is 80 bytes inside a block of size 88 free'd
==7383==    at 0x1B902391: free (in /usr/lib/valgrind/vgpreload_memcheck.so)
==7383==    by 0x1B96B89D: xmlFreeDoc__internal_alias (tree.c:1160)
==7383==    by 0x1B9674B3: xmlParseBalancedChunkMemoryRecover__internal_alias 
(parser.c:11277)
==7383==    by 0x1B9666FC: xmlParseBalancedChunkMemory__internal_alias 
(parser.c:10763)
==7383==
==7383== Invalid read of size 4
==7383==    at 0x1BA133FB: xmlDictOwns__internal_alias (dict.c:709)
==7383==    by 0x1B96EC5C: xmlFreeNodeList__internal_alias (tree.c:3380)
==7383==    by 0x804866A: main (parse2.c:14)
==7383==  Address 0x1BBD38C0 is 16 bytes inside a block of size 24 free'd
==7383==    at 0x1B902391: free (in /usr/lib/valgrind/vgpreload_memcheck.so)
==7383==    by 0x1BA12DCA: xmlDictFree__internal_alias (dict.c:480)
==7383==    by 0x1B96B8B1: xmlFreeDoc__internal_alias (tree.c:1161)
==7383==    by 0x1B9674B3: xmlParseBalancedChunkMemoryRecover__internal_alias 
(parser.c:11277)
==7383==
==7383== Invalid read of size 4
==7383==    at 0x1BA1341A: xmlDictOwns__internal_alias (dict.c:711)
==7383==    by 0x1B96EC5C: xmlFreeNodeList__internal_alias (tree.c:3380)
==7383==    by 0x804866A: main (parse2.c:14)
==7383==  Address 0x1BBD652C is 4 bytes inside a block of size 1024 free'd
==7383==    at 0x1B902391: free (in /usr/lib/valgrind/vgpreload_memcheck.so)
==7383==    by 0x1BA12DAF: xmlDictFree__internal_alias (dict.c:477)
==7383==    by 0x1B96B8B1: xmlFreeDoc__internal_alias (tree.c:1161)
==7383==    by 0x1B9674B3: xmlParseBalancedChunkMemoryRecover__internal_alias 
(parser.c:11277)
==7383==
==7383== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 23 from 1)



___parse2.c___
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>


int main (int argc, char **argv) {
    xmlNodePtr nodes  = NULL;
    int retCode;

    LIBXML_TEST_VERSION
    retCode = xmlParseBalancedChunkMemory(NULL,NULL,NULL,0,"<A/>",&nodes);
    xmlFreeNodeList( nodes );
    xmlCleanupParser();
    xmlMemoryDump();
    return(0);
}
__end_of_parse2.c___

Cheers,
-- Petr

Attachment: pgpcc9N3yd2vn.pgp
Description: PGP signature



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