diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2014-03-03 17:13:37 +0100 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2014-03-03 17:13:37 +0100 |
commit | d2aff824dd0900982a420ebaaa1dac6120a9d72e (patch) | |
tree | 20d1eba8c4298bf2cd2716cb16154484c3b8463b | |
parent | 956f650249011e1dcc7665e431cf39063632d377 (diff) | |
download | cython-d2aff824dd0900982a420ebaaa1dac6120a9d72e.tar.gz |
fix crash by excluding heap types from the extension type freelists
-rw-r--r-- | CHANGES.rst | 3 | ||||
-rw-r--r-- | Cython/Compiler/ModuleNode.py | 2 | ||||
-rw-r--r-- | tests/run/exttype_freelist.pyx | 176 |
3 files changed, 180 insertions, 1 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index e4f10ea7d..8be7abbf5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -16,6 +16,9 @@ Features added Bugs fixed ---------- +* Crash when subtyping freelist enabled Cython extension types with + Python classes that use ``__slots__``. + * Memory leak in memory views when copying overlapping, contiguous slices. * Format checking when requesting non-contiguous buffers from diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 041362ca0..9871e3efe 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -1172,7 +1172,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): if is_final_type: abstract_check = '' else: - abstract_check = ' & ((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)' + abstract_check = ' & ((t->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)) == 0)' obj_struct = type.declaration_code("", deref=True) code.putln("if (likely((%s > 0) & (t->tp_basicsize == sizeof(%s))%s)) {" % ( freecount_name, obj_struct, abstract_check)) diff --git a/tests/run/exttype_freelist.pyx b/tests/run/exttype_freelist.pyx index b3ec7b4fa..8f39040d5 100644 --- a/tests/run/exttype_freelist.pyx +++ b/tests/run/exttype_freelist.pyx @@ -12,6 +12,20 @@ cdef class ExtTypeNoGC: >>> obj = ExtTypeNoGC() >>> obj = ExtTypeNoGC() >>> obj = ExtTypeNoGC() + + >>> class PyClass(ExtTypeNoGC): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtTypeNoGC): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ @@ -23,6 +37,20 @@ cdef class ExtSubTypeNoGC(ExtTypeNoGC): >>> obj = ExtSubTypeNoGC() >>> obj = ExtSubTypeNoGC() >>> obj = ExtSubTypeNoGC() + + >>> class PyClass(ExtSubTypeNoGC): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtSubTypeNoGC): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ cdef bytes x @@ -36,6 +64,20 @@ cdef class ExtTypeWithGC: >>> obj = ExtTypeWithGC() >>> obj = ExtTypeWithGC() >>> obj = ExtTypeWithGC() + + >>> class PyClass(ExtTypeWithGC): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtTypeWithGC): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ cdef attribute @@ -63,6 +105,20 @@ cdef class ExtSubType(ExtTypeWithGC): >>> obj = ExtSubType() >>> obj = ExtSubType() >>> obj = ExtSubType() + + >>> class PyClass(ExtSubType): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtSubType): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ @@ -74,6 +130,20 @@ cdef class LargerExtSubType(ExtSubType): >>> obj = LargerExtSubType() >>> obj = LargerExtSubType() >>> obj = LargerExtSubType() + + >>> class PyClass(LargerExtSubType): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(LargerExtSubType): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ cdef attribute2 @@ -90,6 +160,20 @@ cdef class ExtTypeWithCAttr: >>> obj = ExtTypeWithCAttr() >>> obj = ExtTypeWithCAttr() >>> obj = ExtTypeWithCAttr() + + >>> class PyClass(ExtTypeWithCAttr): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtTypeWithCAttr): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ cdef int cattr @@ -106,6 +190,18 @@ cdef class ExtSubTypeWithCAttr(ExtTypeWithCAttr): >>> obj = ExtSubTypeWithCAttr() >>> obj = ExtSubTypeWithCAttr() >>> obj = ExtSubTypeWithCAttr() + + >>> class PyClass(ExtSubTypeWithCAttr): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + + >>> class PyClass(ExtSubTypeWithCAttr): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() """ @@ -119,6 +215,20 @@ cdef class ExtTypeWithCAttrNoFreelist: >>> obj = ExtTypeWithCAttrNoFreelist() >>> obj = ExtTypeWithCAttrNoFreelist() >>> obj = ExtTypeWithCAttrNoFreelist() + + >>> class PyClass(ExtTypeWithCAttrNoFreelist): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtTypeWithCAttrNoFreelist): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ cdef int cattr @@ -148,6 +258,28 @@ cdef class ExtTypeWithCMethods: >>> obj = ExtTypeWithCMethods() >>> test_cmethods(obj) (1, 2) + + >>> class PyClass(ExtTypeWithCMethods): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> test_cmethods(obj) + (1, 2) + >>> obj = PyClass() + >>> test_cmethods(obj) + (1, 2) + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtTypeWithCMethods): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> test_cmethods(obj) + (1, 2) + >>> obj = PyClass() + >>> test_cmethods(obj) + (1, 2) + >>> obj = PyClass() + >>> del PyClass, obj """ cdef int cattr @@ -188,6 +320,20 @@ cdef class ExtSubTypeWithCMethods(ExtTypeWithCMethods): >>> obj = ExtSubTypeWithCMethods() >>> test_cmethods(obj) (1, 2) + + >>> class PyClass(ExtSubTypeWithCMethods): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtSubTypeWithCMethods): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ @@ -232,6 +378,20 @@ cdef class ExtSubTypeWithMoreCMethods(ExtSubTypeWithCMethods): >>> obj = ExtTypeWithCMethods() >>> test_cmethods(obj) (1, 2) + + >>> class PyClass(ExtSubTypeWithMoreCMethods): a = 1 + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtSubTypeWithMoreCMethods): __slots__ = () + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ def __cinit__(self): assert self.cattr == 1 @@ -270,6 +430,22 @@ cdef class ExtTypeWithRefCycle: True >>> first.attribute = obj >>> del obj, first + + >>> class PyClass(ExtTypeWithRefCycle): a = 1 + >>> obj = PyClass() + >>> obj.attribute = obj + >>> obj.attribute = PyClass(obj) + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj + + >>> class PyClass(ExtTypeWithRefCycle): __slots__ = () + >>> obj = PyClass() + >>> obj.attribute = obj + >>> obj.attribute = PyClass(obj) + >>> obj = PyClass() + >>> obj = PyClass() + >>> del PyClass, obj """ cdef public attribute |