libxml2 bug report - 2002/01/30 =============================== the following applies to libxml2-2.4.13 Issued as BUG #70067 This bug has been fixed on 2002-02-08 by daniel@veillard.com BugTracking: ,-----------> | ------- Additional Comments From daniel@veillard.com 2002-02-08 08:23 ------- | Okay, thanks a lot for the report, fixed in CVS, | | Daniel | Status: RESOLVED | | ------- Additional Comments From daniel@veillard.com 2002-02-12 03:40 ------- | Okay this should be fixed in 2.4.15, | | thanks for the report, | Status: CLOSED `-------------------------> This document has been last modified on 2002-02-12 (for the code snippets refer to the end of this file) Consider code snippet 1, which adds the same node to two different xmlDoc's. That code works perfectly fine, if/because xmlUnlinkNode() is called manually. If you run the code, you'll notice that root->doc is NULL, even after xmlDocSetRootElement() (is there any reason for this?). Now take a look at code snippet 2. It tries to do the same thing, only with the doc's root node. Is seems to run just fine, but executing that code with malloc debugging hooks enabled makes the beast show it's teeth: pointers are passed to free() more than once... $ MALLOC_CHECK_=1 ./xmltest malloc: using debugging hooks root->doc = (nil) free(): invalid pointer 0x80499f8! free(): invalid pointer 0x80499b8! Of course, a quick look at xmlUnlinkNode() shows that it does not handle the "node is root" case. And currently it's impossible to handle that case in that function, because root->parent and root->doc (!!) are untouched; e.g. the root node of a document will not get it's ->doc ptr assigned correctly (/ at all). regards, -lukas Code Snippet 1 (works): ======================== /*********************************************************************/ #include #include #include #include int main(int argc, char *argv[]) { xmlDoc *doc,*doc2; xmlNode *root, *node; node = xmlNewNode(NULL, "node1"); doc = xmlNewDoc("1.0"); root = xmlNewNode(NULL, "root1"); xmlDocSetRootElement(doc, root); fprintf(stderr, "root->doc = %p\n", root->doc); xmlAddChild(root, node); doc2 = xmlNewDoc("1.0"); root = xmlNewNode(NULL, "root2"); xmlDocSetRootElement(doc2, root); fprintf(stderr, "root->doc = %p\n", root->doc); /* root->doc will be NULL */ /* manual unlinking is necessary to prevent duplicate calls to free() * on the same pointer at xmlFreeDoc() time */ xmlUnlinkNode(node); xmlAddChild(root, node); xmlFreeDoc(doc); xmlFreeDoc(doc2); return 0; } /*********************************************************************/ Code Snippet 1 (currupt's memory): ================================== /*********************************************************************/ #include #include #include #include int main(int argc, char *argv[]) { xmlDoc *doc,*doc2; xmlNode *root; doc = xmlNewDoc("1.0"); root = xmlNewNode(NULL, "root1"); xmlDocSetRootElement(doc, root); doc2 = xmlNewDoc("1.0"); /* adding the same root to doc2 as to doc */ xmlUnlinkNode(root); /* unlinking as no effect! */ xmlDocSetRootElement(doc2, root); fprintf(stderr, "root->doc = %p\n", root->doc); xmlFreeDoc(doc); xmlFreeDoc(doc2); return 0; } /*********************************************************************/