From 6ede65480bd907ed17bddacd19b13da30d5d1140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santhosh=20=2EI=20=F0=9F=A6=87?= Date: Tue, 14 Jul 2026 21:49:03 +0530 Subject: [PATCH] gh-151912: Fix segfault in `type()` with NULL `tp_new` metaclasses (GH-151916) (cherry picked from commit f160f16373f9ea3f636bc5cd6fb4be7e150bb27f) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Santhosh .I 🦇 --- Lib/test/test_descr.py | 9 +++++++++ .../2026-06-22-14-48-22.gh-issue-151912.YcxfnU.rst | 1 + Objects/typeobject.c | 7 +++++++ 3 files changed, 17 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-06-22-14-48-22.gh-issue-151912.YcxfnU.rst diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index b5ed28ec8598239..168f1530cec6002 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -814,6 +814,15 @@ class X(C, int()): class X(int(), C): pass + @unittest.skipIf(_testcapi is None, 'need the _testcapi module') + def test_type_with_null_new_metaclass(self): + metaclass = _testcapi.HeapCTypeMetaclassNullNew + base = _testcapi.pytype_fromspec_meta(metaclass) + + # Exercise type_new's metaclass selection path, not a direct call. + with self.assertRaisesRegex(TypeError, r"cannot create '.*' instances"): + type("Derived", (base,), {}) + def test_module_subclasses(self): # Testing Python subclass of module... log = [] diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-22-14-48-22.gh-issue-151912.YcxfnU.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-22-14-48-22.gh-issue-151912.YcxfnU.rst new file mode 100644 index 000000000000000..07b73949b438a33 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-22-14-48-22.gh-issue-151912.YcxfnU.rst @@ -0,0 +1 @@ +Fixed a crash in ``type()`` when selecting a metaclass whose ``tp_new`` slot is ``NULL``. Such metaclasses are now rejected with ``TypeError`` instead of causing a NULL pointer dereference. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index bbdfbfc03c98b19..714288bc4150887 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4253,6 +4253,13 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) if (winner != ctx->metatype) { if (winner->tp_new != type_new) { + /* Check if tp_new is NULL (cannot instantiate this type) */ + if (winner->tp_new == NULL) { + PyErr_Format(PyExc_TypeError, + "cannot create '%.400s' instances", + winner->tp_name); + return -1; + } /* Pass it to the winner */ *type = winner->tp_new(winner, ctx->args, ctx->kwds); if (*type == NULL) {