summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2014-03-03 17:13:37 +0100
committerStefan Behnel <stefan_ml@behnel.de>2014-03-03 17:13:37 +0100
commitd2aff824dd0900982a420ebaaa1dac6120a9d72e (patch)
tree20d1eba8c4298bf2cd2716cb16154484c3b8463b
parent956f650249011e1dcc7665e431cf39063632d377 (diff)
downloadcython-d2aff824dd0900982a420ebaaa1dac6120a9d72e.tar.gz
fix crash by excluding heap types from the extension type freelists
-rw-r--r--CHANGES.rst3
-rw-r--r--Cython/Compiler/ModuleNode.py2
-rw-r--r--tests/run/exttype_freelist.pyx176
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