Skip to content

Commit 5e5b242

Browse files
authored
Mark extension types as immutable (#5023)
Since python/cpython#25520 types are automatically marked as immutable if they are static. While we still have the Py_TPFLAGS_HEAPTYPE hack in place we need to manually mark our types as immutable. It's possible to crash Python by trying to modify mutable static types.
1 parent ddd11a2 commit 5e5b242

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

Cython/Utility/ExtensionTypes.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,15 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
230230
// Other than this check, the Py_TPFLAGS_HEAPTYPE flag is unused
231231
// in PyType_Ready().
232232
t->tp_flags |= Py_TPFLAGS_HEAPTYPE;
233+
#if PY_VERSION_HEX >= 0x030A0000
234+
// As of https://github.com/python/cpython/pull/25520
235+
// PyType_Ready marks types as immutable if they are static types
236+
// and requires the Py_TPFLAGS_IMMUTABLETYPE flag to mark types as
237+
// immutable
238+
// Manually set the Py_TPFLAGS_IMMUTABLETYPE flag, since the type
239+
// is immutable
240+
t->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
241+
#endif
233242
#else
234243
// avoid C warning about unused helper function
235244
(void)__Pyx_PyObject_CallMethod0;

tests/run/cclass_assign_attr_GH3100.pyx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
cdef extern from *:
2+
"""
3+
#ifdef CYTHON_USE_TYPE_SPECS
4+
#define TYPESPECS 1
5+
#else
6+
#define TYPESPECS 0
7+
#endif
8+
"""
9+
int TYPESPECS
10+
111
cdef class Foo:
212
"""
313
>>> D = Foo.__dict__
@@ -17,3 +27,37 @@ cdef class Foo:
1727
meth2 = meth
1828
classmeth2 = classmeth
1929
staticmeth2 = staticmeth
30+
31+
cdef class ChangeName:
32+
# the class seems to need some contents for changing the
33+
# name to cause a problem
34+
cdef public str attr1
35+
cdef public int attr2
36+
37+
if TYPESPECS:
38+
__doc__ = """
39+
For typespecs, cdef classes are mutable on some Python versions
40+
(and it's easiest to leave them that way). Therefore the test
41+
is just that reassigning the name doesn't cause a crash
42+
43+
>>> try:
44+
... ChangeName.__name__ = "SomethingElse"
45+
... except TypeError:
46+
... pass # either type error or changing the name is fine
47+
"""
48+
else:
49+
__doc__ = """
50+
GH-5079
51+
Assigning to the cdef class name shouldn't cause a crash.
52+
The important bit of this test is the not crashing - it's
53+
possible that typespec/limited-API defined classes will be
54+
naturally mutable and that isn't a huge problem
55+
56+
>>> ChangeName.__name__ = "SomethingElse" # doctest: +ELLIPSIS
57+
Traceback (most recent call last):
58+
...
59+
TypeError: ...
60+
>>> ChangeName.__name__
61+
'ChangeName'
62+
"""
63+

0 commit comments

Comments
 (0)