From 40bf263f18748df8865f55817fbc90c2517533d5 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 7 Apr 2025 12:50:53 +0300 Subject: [PATCH 1/4] gh-132176: Fix crash on `type()` when `tuple` subclass passed as `bases` --- Lib/test/test_types.py | 13 +++++++++++++ .../2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst | 2 ++ Objects/typeobject.c | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index f9e12931a63e4f..5769d62dacc1ec 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1819,6 +1819,19 @@ class Model(metaclass=ModelBase): with self.assertRaises(RuntimeWarning): type("SouthPonies", (Model,), {}) + def test_tuple_subclass_as_bases(self): + # gh-132176: it used to crash on using + # tuple subclass for as base classes. + class TupleSubclass(tuple): pass + + typ = type("typ", TupleSubclass((int, object)), {}) + self.assertTrue(issubclass(typ, int)) + self.assertTrue(issubclass(typ, object)) + self.assertFalse(issubclass(typ, tuple)) + self.assertIsInstance(typ(), int) + self.assertIsInstance(typ(), object) + self.assertNotIsInstance(typ(), tuple) + class SimpleNamespaceTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst new file mode 100644 index 00000000000000..fe955a40be6270 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst @@ -0,0 +1,2 @@ +Fix a crash when :func:`type` receives a :class:`tuple` subclass as the +second *bases* argument. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index b92eaefc90d0af..1922739af98f7b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -497,10 +497,11 @@ _PyType_GetBases(PyTypeObject *self) static inline void set_tp_bases(PyTypeObject *self, PyObject *bases, int initial) { - assert(PyTuple_CheckExact(bases)); + assert(PyTuple_Check(bases)); if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) { // XXX tp_bases can probably be statically allocated for each // static builtin type. + assert(PyTuple_CheckExact(bases)); assert(initial); assert(self->tp_bases == NULL); if (PyTuple_GET_SIZE(bases) == 0) { From 603eb00f9be04e6d384e81411b13a00b07b0ccfa Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 14 Apr 2025 23:03:50 +0300 Subject: [PATCH 2/4] Delete Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst --- .../2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst deleted file mode 100644 index fe955a40be6270..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-07-12-50-10.gh-issue-132176.PRDbkA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash when :func:`type` receives a :class:`tuple` subclass as the -second *bases* argument. From b04c998ec7c8678f922f573a1ce2eb7cd543c2aa Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 15 Apr 2025 11:58:51 +0300 Subject: [PATCH 3/4] Update Lib/test/test_types.py --- Lib/test/test_types.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 5769d62dacc1ec..4048c359a5968d 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1825,12 +1825,7 @@ def test_tuple_subclass_as_bases(self): class TupleSubclass(tuple): pass typ = type("typ", TupleSubclass((int, object)), {}) - self.assertTrue(issubclass(typ, int)) - self.assertTrue(issubclass(typ, object)) - self.assertFalse(issubclass(typ, tuple)) - self.assertIsInstance(typ(), int) - self.assertIsInstance(typ(), object) - self.assertNotIsInstance(typ(), tuple) + self.assertEqual(typ.__bases__, (int, object)) class SimpleNamespaceTests(unittest.TestCase): From b4b7f129d9f30846db9b8501c1c9e761a29d9d54 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 15 Apr 2025 12:39:45 +0300 Subject: [PATCH 4/4] Update Lib/test/test_types.py Co-authored-by: Victor Stinner --- Lib/test/test_types.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 4048c359a5968d..ab70e75d63703d 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1826,6 +1826,7 @@ class TupleSubclass(tuple): pass typ = type("typ", TupleSubclass((int, object)), {}) self.assertEqual(typ.__bases__, (int, object)) + self.assertEqual(type(typ.__bases__), TupleSubclass) class SimpleNamespaceTests(unittest.TestCase):