Skip to content

Commit e772061

Browse files
[3.13] pythongh-138479: Ensure that __typing_subst__ returns a tuple (pythonGH-138482) (pythonGH-138786)
* pythongh-138479: Ensure that `__typing_subst__` returns a tuple (pythonGH-138482) Raise an exception if __typing_subst__ returns a non-tuple object. (cherry picked from commit 1da989b) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 7195d7f commit e772061

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

Lib/test/test_typing.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5706,6 +5706,23 @@ class A:
57065706
with self.assertRaises(TypeError):
57075707
a[int]
57085708

5709+
def test_return_non_tuple_while_unpacking(self):
5710+
# GH-138497: GenericAlias objects didn't ensure that __typing_subst__ actually
5711+
# returned a tuple
5712+
class EvilTypeVar:
5713+
__typing_is_unpacked_typevartuple__ = True
5714+
def __typing_prepare_subst__(*_):
5715+
return None # any value
5716+
def __typing_subst__(*_):
5717+
return 42 # not tuple
5718+
5719+
evil = EvilTypeVar()
5720+
# Create a dummy TypeAlias that will be given the evil generic from
5721+
# above.
5722+
type type_alias[*_] = 0
5723+
with self.assertRaisesRegex(TypeError, ".+__typing_subst__.+tuple.+int.*"):
5724+
type_alias[evil][0]
5725+
57095726

57105727
class ClassVarTests(BaseTestCase):
57115728

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash when a generic object's ``__typing_subst__`` returns an object
2+
that isn't a :class:`tuple`.

Objects/genericaliasobject.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,11 +517,22 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
517517
return NULL;
518518
}
519519
if (unpack) {
520+
if (!PyTuple_Check(arg)) {
521+
Py_DECREF(newargs);
522+
Py_DECREF(item);
523+
PyObject *original = PyTuple_GET_ITEM(args, iarg);
524+
PyErr_Format(PyExc_TypeError,
525+
"expected __typing_subst__ of %T objects to return a tuple, not %T",
526+
original, arg);
527+
Py_DECREF(arg);
528+
return NULL;
529+
}
520530
jarg = tuple_extend(&newargs, jarg,
521531
&PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg));
522532
Py_DECREF(arg);
523533
if (jarg < 0) {
524534
Py_DECREF(item);
535+
assert(newargs == NULL);
525536
return NULL;
526537
}
527538
}

0 commit comments

Comments
 (0)