bpo-43908: check_set_special_type_attr() checks Py_TPFLAGS_IMMUTABLETYPE (GH-25743)

check_set_special_type_attr() and type_set_annotations()
now check for immutable flag (Py_TPFLAGS_IMMUTABLETYPE).

Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Erlend Egeberg Aasland 2021-04-30 15:25:43 +02:00 committed by GitHub
parent 9032cf5cb1
commit 64141382ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 9 deletions

View File

@ -4763,12 +4763,14 @@ order (MRO) for bases """
"elephant" "elephant"
X.__doc__ = "banana" X.__doc__ = "banana"
self.assertEqual(X.__doc__, "banana") self.assertEqual(X.__doc__, "banana")
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
type(list).__dict__["__doc__"].__set__(list, "blah") type(list).__dict__["__doc__"].__set__(list, "blah")
self.assertIn("can't set list.__doc__", str(cm.exception)) self.assertIn("cannot set '__doc__' attribute of immutable type 'list'", str(cm.exception))
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
type(X).__dict__["__doc__"].__delete__(X) type(X).__dict__["__doc__"].__delete__(X)
self.assertIn("can't delete X.__doc__", str(cm.exception)) self.assertIn("cannot delete '__doc__' attribute of immutable type 'X'", str(cm.exception))
self.assertEqual(X.__doc__, "banana") self.assertEqual(X.__doc__, "banana")
def test_qualname(self): def test_qualname(self):

View File

@ -466,14 +466,16 @@ static PyMemberDef type_members[] = {
static int static int
check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name) check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name)
{ {
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"can't set %s.%s", type->tp_name, name); "cannot set '%s' attribute of immutable type '%s'",
name, type->tp_name);
return 0; return 0;
} }
if (!value) { if (!value) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"can't delete %s.%s", type->tp_name, name); "cannot delete '%s' attribute of immutable type '%s'",
name, type->tp_name);
return 0; return 0;
} }
@ -978,8 +980,10 @@ type_get_annotations(PyTypeObject *type, void *context)
static int static int
type_set_annotations(PyTypeObject *type, PyObject *value, void *context) type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
{ {
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) {
PyErr_Format(PyExc_TypeError, "can't set attributes of built-in/extension type '%s'", type->tp_name); PyErr_Format(PyExc_TypeError,
"cannot set '__annotations__' attribute of immutable type '%s'",
type->tp_name);
return -1; return -1;
} }
@ -3953,8 +3957,8 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
PyErr_Format( PyErr_Format(
PyExc_TypeError, PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'", "cannot set %R attribute of immutable type '%s'",
type->tp_name); name, type->tp_name);
return -1; return -1;
} }
if (PyUnicode_Check(name)) { if (PyUnicode_Check(name)) {