https://github.com/python/cpython/commit/c0006faf4f48f01126a8a0752da8f159142e410d
commit: c0006faf4f48f01126a8a0752da8f159142e410d
branch: main
author: Darius Houle <[email protected]>
committer: JelleZijlstra <[email protected]>
date: 2026-08-13T22:14:24-07:00
summary:

gh-155752: Do not crash when GenericAlias parameters change during substitution 
(#155761)

An alias argument can gain __typing_subst__ after __parameters__ has been 
cached, including during a preparation or substitution callback. Check that the 
argument is present before indexing the substitution arguments.

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-08-13-13-50-00.gh-issue-155752.Rp7K2x.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 2875303fb15619..f35f864dce21e8 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -6054,6 +6054,22 @@ class A:
                     with self.assertRaises(TypeError):
                         a[int]
 
+    def test_parameter_added_after_parameters_cached(self):
+        # gh-155752: GenericAlias parameters are cached before substitution, so
+        # an argument can gain __typing_subst__ after the tuple is calculated.
+        class Parameter:
+            pass
+
+        first = Parameter()
+        first.__typing_subst__ = lambda value: value
+        late = Parameter()
+        alias = types.GenericAlias(dict, (first, late))
+        self.assertEqual(alias.__parameters__, (first,))
+        late.__typing_subst__ = lambda value: value
+
+        with self.assertRaisesRegex(TypeError, "not found in __parameters__"):
+            alias[0]
+
     def test_return_non_tuple_while_unpacking(self):
         # GH-138497: GenericAlias objects didn't ensure that __typing_subst__ 
actually
         # returned a tuple
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-13-13-50-00.gh-issue-155752.Rp7K2x.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-13-13-50-00.gh-issue-155752.Rp7K2x.rst
new file mode 100644
index 00000000000000..300e97ad5d257b
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-13-13-50-00.gh-issue-155752.Rp7K2x.rst
@@ -0,0 +1,2 @@
+Fix a crash when a :class:`types.GenericAlias` argument gains a
+``__typing_subst__`` hook after the alias parameters have been cached.
diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
index 1504adb950ef44..8bb7cc8c74a592 100644
--- a/Objects/genericaliasobject.c
+++ b/Objects/genericaliasobject.c
@@ -525,8 +525,18 @@ _Py_subs_parameters(PyObject *self, PyObject *args, 
PyObject *parameters, PyObje
         }
         if (subst) {
             Py_ssize_t iparam = tuple_index(parameters, nparams, arg);
-            assert(iparam >= 0);
-            arg = PyObject_CallOneArg(subst, argitems[iparam]);
+            if (iparam < 0) {
+                // __parameters__ may be stale if an argument gained
+                // __typing_subst__ after the tuple was computed.
+                PyErr_Format(PyExc_TypeError,
+                             "argument %R with __typing_subst__ was not found "
+                             "in __parameters__",
+                             arg);
+                arg = NULL;
+            }
+            else {
+                arg = PyObject_CallOneArg(subst, argitems[iparam]);
+            }
             Py_DECREF(subst);
         }
         else {

_______________________________________________
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