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]