http://bugs.winehq.org/show_bug.cgi?id=33450
--- Comment #5 from Nikolay Sivov bunglehead@gmail.com 2013-05-03 15:04:51 CDT --- It doesn't depend on libxml2 version, in fact crash was caused by the very same thing. Libxml2 has a habit to "optimize" away adjacent text nodes, so when you add a new text child it checks if it will be added next to existing text node, then it will merge text data and free passed child node. Relevant piece of code from xmlAddChild():
--- /* * If cur is a TEXT node, merge its content with adjacent TEXT nodes * cur is then freed. */ if (cur->type == XML_TEXT_NODE) { if ((parent->type == XML_TEXT_NODE) && (parent->content != NULL) && (parent->name == cur->name)) { xmlNodeAddContent(parent, cur->content); xmlFreeNode(cur); return(parent); } if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) && (parent->last->name == cur->name) && (parent->last != cur)) { xmlNodeAddContent(parent->last, cur->content); xmlFreeNode(cur); return(parent->last); } } ---
'cur' here is what's passed as child to add to the tree. That of course leads to DOM tree going out of sync with libxml2 tree and eventually it will double free or access freed memory. It's possible to have our own xmlAddChild() version that is not that smart and preserves all nodes, but the question here is what will potentially break next in libxml2 when a tree gets several text siblings next to each other. I'll check if it makes any assumptions about that, and probably will check with author too.