summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2012-12-14 08:08:33 +0100
committerStefan Behnel <stefan_ml@behnel.de>2012-12-14 08:08:33 +0100
commit8541d7be70846c6ae6b32bc7e69121ebd23f1606 (patch)
tree88da2d10a52de5e4121c783fa3fd090bb6fecfd4
parentdfb2d7459814fce8f7456e84248e6f8fdb35020e (diff)
downloadcython-8541d7be70846c6ae6b32bc7e69121ebd23f1606.tar.gz
fix crash bug during final cleanup for cimported base types
-rw-r--r--CHANGES.rst2
-rw-r--r--Cython/Utility/ExtensionTypes.c21
2 files changed, 17 insertions, 6 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index e40bd590e..7bd2ad05f 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -11,6 +11,8 @@ Features added
Bugs fixed
----------
+* During final interpreter cleanup (with types cleanup enabled at compile time), extension types that inherit from base types over more than one level that were cimported from other modules could lead to a crash.
+
* In CPython 3.3, converting a Unicode character to the Py_UNICODE type could fail to raise an overflow for non-BMP characters that do not fit into a wchar_t on the current platform.
* Negative C integer constants lost their longness suffix in the generated C code.
diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c
index 1e06ba13c..423ed9673 100644
--- a/Cython/Utility/ExtensionTypes.c
+++ b/Cython/Utility/ExtensionTypes.c
@@ -7,10 +7,13 @@ static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_deal
static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc) {
PyTypeObject* type = Py_TYPE(obj);
+ /* try to find the first parent type that has a different tp_dealloc() function */
while (type && type->tp_dealloc != current_tp_dealloc)
type = type->tp_base;
- if (type && type->tp_base)
- type->tp_base->tp_dealloc(obj);
+ while (type && type->tp_dealloc == current_tp_dealloc)
+ type = type->tp_base;
+ if (type)
+ type->tp_dealloc(obj);
}
/////////////// CallNextTpTraverse.proto ///////////////
@@ -21,10 +24,13 @@ static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, trav
static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, traverseproc current_tp_traverse) {
PyTypeObject* type = Py_TYPE(obj);
+ /* try to find the first parent type that has a different tp_traverse() function */
while (type && type->tp_traverse != current_tp_traverse)
type = type->tp_base;
- if (type && type->tp_base && type->tp_base->tp_traverse)
- return type->tp_base->tp_traverse(obj, v, a);
+ while (type && type->tp_traverse == current_tp_traverse)
+ type = type->tp_base;
+ if (type && type->tp_traverse)
+ return type->tp_traverse(obj, v, a);
// FIXME: really ignore?
return 0;
}
@@ -37,8 +43,11 @@ static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_dealloc);
static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) {
PyTypeObject* type = Py_TYPE(obj);
+ /* try to find the first parent type that has a different tp_clear() function */
while (type && type->tp_clear != current_tp_clear)
type = type->tp_base;
- if (type && type->tp_base && type->tp_base->tp_clear)
- type->tp_base->tp_clear(obj);
+ while (type && type->tp_clear == current_tp_clear)
+ type = type->tp_base;
+ if (type && type->tp_clear)
+ type->tp_clear(obj);
}