https://github.com/python/cpython/commit/e7720612eafd4b049892e83da3239447b57b9a6e
commit: e7720612eafd4b049892e83da3239447b57b9a6e
branch: 3.13
author: Peter Bierma <[email protected]>
committer: ZeroIntensity <[email protected]>
date: 2025-09-11T11:08:57Z
summary:

[3.13] gh-138479: Ensure that `__typing_subst__` returns a tuple (GH-138482) 
(GH-138786)

* gh-138479: Ensure that `__typing_subst__` returns a tuple (GH-138482)

Raise an exception if __typing_subst__ returns a non-tuple object.

(cherry picked from commit 1da989be74eaa94590ec28e750e5352de1ead227)

Co-authored-by: Serhiy Storchaka <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-09-03-17-00-30.gh-issue-138479.qUxgWs.rst
M Lib/test/test_typing.py
M Objects/genericaliasobject.c

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index e1115809d4f390..5f49bf757096f0 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -5706,6 +5706,23 @@ class A:
                     with self.assertRaises(TypeError):
                         a[int]
 
+    def test_return_non_tuple_while_unpacking(self):
+        # GH-138497: GenericAlias objects didn't ensure that __typing_subst__ 
actually
+        # returned a tuple
+        class EvilTypeVar:
+            __typing_is_unpacked_typevartuple__ = True
+            def __typing_prepare_subst__(*_):
+                return None  # any value
+            def __typing_subst__(*_):
+                return 42  # not tuple
+
+        evil = EvilTypeVar()
+        # Create a dummy TypeAlias that will be given the evil generic from
+        # above.
+        type type_alias[*_] = 0
+        with self.assertRaisesRegex(TypeError, 
".+__typing_subst__.+tuple.+int.*"):
+            type_alias[evil][0]
+
 
 class ClassVarTests(BaseTestCase):
 
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-03-17-00-30.gh-issue-138479.qUxgWs.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-03-17-00-30.gh-issue-138479.qUxgWs.rst
new file mode 100644
index 00000000000000..c94640af3b053c
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-03-17-00-30.gh-issue-138479.qUxgWs.rst
@@ -0,0 +1,2 @@
+Fix a crash when a generic object's ``__typing_subst__`` returns an object
+that isn't a :class:`tuple`.
diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
index bf1838061e9eb1..4bb84f054dd3dd 100644
--- a/Objects/genericaliasobject.c
+++ b/Objects/genericaliasobject.c
@@ -517,11 +517,22 @@ _Py_subs_parameters(PyObject *self, PyObject *args, 
PyObject *parameters, PyObje
             return NULL;
         }
         if (unpack) {
+            if (!PyTuple_Check(arg)) {
+                Py_DECREF(newargs);
+                Py_DECREF(item);
+                PyObject *original = PyTuple_GET_ITEM(args, iarg);
+                PyErr_Format(PyExc_TypeError,
+                             "expected __typing_subst__ of %T objects to 
return a tuple, not %T",
+                             original, arg);
+                Py_DECREF(arg);
+                return NULL;
+            }
             jarg = tuple_extend(&newargs, jarg,
                     &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg));
             Py_DECREF(arg);
             if (jarg < 0) {
                 Py_DECREF(item);
+                assert(newargs == NULL);
                 return NULL;
             }
         }

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to