On Mon, Mar 10, 2008 at 06:43:02PM -0700, William M. Brack wrote:
> Martin (gzlist) wrote:
> > I attach a simple python script (libxml2_crash.py) that seems to
> >  reference uninitialised memory, or crash the interpreter.
> >
> <snip>
> >  I tried the simplest C equivalent I could cook up from the docs
> >  (attached libxml2_nocrash.c) which behaves itself, perhaps
> > suggesting
> >  the problem's in the python bindings. Could someone with a good
> >  understanding of the lib can get a better idea of what exactly is
> > up?
> >
> >  Martin
> 
> I traced through quite a bit, and was able to isolate where and what
> the problem is.  Unfortunately, I can't spend much time on libxml2
> for the next couple of weeks, so I have opened a bug
> (http://bugzilla.gnome.org/show_bug.cgi?id=521699) which describes
> how far I got with it.

  yup, agreed with your analysis. That the only case where nodes returned
from an XPath query do not pertain to the document and hence have a different
lifetime.

`
> Perhaps another list member may be able to pursue this?  Python
> bindings are always fun to work on....

  I managed to find a minimalist but correct way to fix this, basically
get python to destroy the namespace node when it garbage collect the
associated python object and remove it from the nodeset before it is being
freed, this seems to work quite well actually. Patch attached, I will also
commit a specific regression test. Note that libxslt/python/types.c need
to be patched too.

Daniel

-- 
Red Hat Virtualization group http://redhat.com/virtualization/
Daniel Veillard      | virtualization library  http://libvirt.org/
[EMAIL PROTECTED]  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine  http://rpmfind.net/
Index: python/types.c
===================================================================
--- python/types.c      (revision 3702)
+++ python/types.c      (working copy)
@@ -7,6 +7,7 @@
  * [EMAIL PROTECTED]
  */
 #include "libxml_wrap.h"
+#include <libxml/xpathInternals.h>
 
 PyObject *
 libxml_intWrap(int val)
@@ -330,6 +331,24 @@
     return (ret);
 }
 
+/**
+ * libxml_xmlXPathDestructNsNode:
+ * cobj: xmlNsPtr namespace node
+ * desc: ignored string
+ *
+ * This function is called if and when a namespace node returned in
+ * an XPath node set is to be destroyed. That's the only kind of
+ * object returned in node set not directly linked to the original
+ * xmlDoc document, see xmlXPathNodeSetDupNs.
+ */
+static void
+libxml_xmlXPathDestructNsNode(void *cobj, void *desc ATTRIBUTE_UNUSED) {
+#ifdef DEBUG
+    fprintf(stderr, "libxml_xmlXPathDestructNsNode called %p\n", cobj);
+#endif
+    xmlXPathNodeSetFreeNs((xmlNsPtr) cobj);
+}
+
 PyObject *
 libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj)
 {
@@ -380,8 +399,17 @@
                 ret = PyList_New(obj->nodesetval->nodeNr);
                 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
                     node = obj->nodesetval->nodeTab[i];
-                    /* TODO: try to cast directly to the proper node type */
-                    PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
+                    if (node->type == XML_NAMESPACE_DECL) {
+                       PyObject *ns = 
+                           PyCObject_FromVoidPtrAndDesc((void *) node,
+                                     (char *) "xmlNsPtr",
+                                    libxml_xmlXPathDestructNsNode);
+                       PyList_SetItem(ret, i, ns);
+                       /* make sure the xmlNsPtr is not destroyed now */
+                       obj->nodesetval->nodeTab[i] = NULL;
+                   } else {
+                       PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
+                   }
                 }
             }
             break;
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
[email protected]
http://mail.gnome.org/mailman/listinfo/xml

Reply via email to