]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.15] gh-151912: Fix segfault in `type()` with NULL `tp_new` metaclasses (GH-151916...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 14 Jul 2026 16:52:23 +0000 (18:52 +0200)
committerGitHub <noreply@github.com>
Tue, 14 Jul 2026 16:52:23 +0000 (16:52 +0000)
gh-151912: Fix segfault in `type()` with NULL `tp_new` metaclasses (GH-151916)
(cherry picked from commit f160f16373f9ea3f636bc5cd6fb4be7e150bb27f)

Co-authored-by: Santhosh .I 🦇 <santhoshilaiyaraja2006@gmail.com>
Lib/test/test_descr.py
Misc/NEWS.d/next/Core_and_Builtins/2026-06-22-14-48-22.gh-issue-151912.YcxfnU.rst [new file with mode: 0644]
Objects/typeobject.c

index 8a8e70214e27ae98900e0b7d480de233e70452c7..ba504119d294fd321d9a172ccdc77472619c3286 100644 (file)
@@ -815,6 +815,15 @@ class ClassPropertiesAndMethods(unittest.TestCase):
             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 (file)
index 0000000..07b7394
--- /dev/null
@@ -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.
index 969ae450013a311243260bade08f431b0d5a887a..f763f9f5eba58fb32f456798d73260d2f7e23b32 100644 (file)
@@ -5026,6 +5026,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) {