[Pyrex] bug if exception is being generated in pyrex constructor

Gustavo Sverzut Barbieri barbieri at gmail.com
Wed May 2 17:16:45 UTC 2007


On 5/2/07, Gustavo Sverzut Barbieri <barbieri at gmail.com> wrote:
> Attached is a test case that shows pyrex generated extension type
> segfaulting if it inherits from a class that raised an exception in
> its constructor.
>
> cdef class A:
>     def __new__(self):
>         raise Exception("crash-me")
>
> cdef class B(A):
>     def __new__(self):
>         print "hello world"
>
> creating B() segfaults because generated code has:
>
> static PyObject *__pyx_tp_new_5myext_B(PyTypeObject *t, PyObject *a,
> PyObject *k) {
>   PyObject *o = __pyx_ptype_5myext_A->tp_new(t, a, k);
>   if (__pyx_f_5myext_1B___new__(o, a, k) < 0) {
>     Py_DECREF(o); o = 0;
>   }
>   return o;
> }
>
> then it segfaults because inside __pyx_f_5myext_1B___new__() it access
> "o", now NULL.
>
> I've got to found this after Greg replied to my last mail. I got this
> same error, but thought it had something to do with not using "public"
> or things like that. But after Greg said the correct way was that, I
> started debugging and found this was the problem... in my binding test
> case I was giving the class an invalid type, raising and exception and
> causing the segfault! :-)

Attached is a patch to fix this issue. It just checks for the NULL
pointer and returns if it's the case.

-- 
Gustavo Sverzut Barbieri
--------------------------------------
Jabber: barbieri at gmail.com
   MSN: barbieri at gmail.com
  ICQ#: 17249123
 Skype: gsbarbieri
Mobile: +55 (81) 9927 0010
-------------- next part --------------
diff -ur Pyrex-0.9.5.1a/Pyrex/Compiler/ModuleNode.py Pyrex-0.9.5.1a-fix/Pyrex/Compiler/ModuleNode.py
--- Pyrex-0.9.5.1a/Pyrex/Compiler/ModuleNode.py	2007-01-27 01:21:03.000000000 -0300
+++ Pyrex-0.9.5.1a-fix/Pyrex/Compiler/ModuleNode.py	2007-05-02 13:38:53.000000000 -0300
@@ -428,6 +428,7 @@
             code.putln(
                 "PyObject *o = %s->tp_new(t, a, k);" %
                     base_type.typeptr_cname)
+            code.putln("if (o == NULL) return NULL;")
         else:
             code.putln(
                 "PyObject *o = (*t->tp_alloc)(t, 0);")


More information about the Pyrex mailing list