Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
from test.support import (
captured_stderr, cpython_only, requires_docstrings, import_helper, run_code,
subTests, EqualToForwardRef,
exceeds_recursion_limit, skip_if_huge_c_stack, skip_wasi_stack_overflow,
skip_emscripten_stack_overflow,
)
from test.typinganndata import (
ann_module695, mod_generics_cache, _typed_dict_helper,
Expand Down Expand Up @@ -5089,6 +5091,17 @@ class MM2(collections.abc.MutableMapping, MutableMapping[str, str]):
pass
self.assertEqual(MM2.__bases__, (collections.abc.MutableMapping, Generic))

@cpython_only
@skip_if_huge_c_stack()
@skip_wasi_stack_overflow()
@skip_emscripten_stack_overflow()
def test_parameters_deep_recursion(self):
x = [0]
for _ in range(exceeds_recursion_limit()):
x = [x]
with self.assertRaisesRegex(RecursionError, "in __parameter__ calculation"):
list[x].__parameters__

def test_orig_bases(self):
T = TypeVar('T')
class C(typing.Dict[str, T]): ...
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix a crash when getting deeply nested ``__parameters__`` from a
:class:`types.GenericAlias` objects.
30 changes: 17 additions & 13 deletions Objects/genericaliasobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ PyObject *
_Py_make_parameters(PyObject *args)
{
assert(PyTuple_Check(args) || PyList_Check(args));
if (Py_EnterRecursiveCall(" in __parameter__ calculation")) {
return NULL;
}

const bool is_args_list = PyList_Check(args);
PyObject *tuple_args = NULL;
if (is_args_list) {
Expand All @@ -210,9 +214,7 @@ _Py_make_parameters(PyObject *args)
}
int rc = PyObject_HasAttrWithError(t, &_Py_ID(__typing_subst__));
if (rc < 0) {
Py_DECREF(parameters);
Py_XDECREF(tuple_args);
return NULL;
goto error;
}
if (rc) {
iparam += tuple_add(parameters, iparam, t);
Expand All @@ -221,18 +223,14 @@ _Py_make_parameters(PyObject *args)
PyObject *subparams;
if (PyObject_GetOptionalAttr(t, &_Py_ID(__parameters__),
&subparams) < 0) {
Py_DECREF(parameters);
Py_XDECREF(tuple_args);
return NULL;
goto error;
}
if (!subparams && (PyTuple_Check(t) || PyList_Check(t))) {
// Recursively call _Py_make_parameters for lists/tuples and
// add the results to the current parameters.
subparams = _Py_make_parameters(t);
if (subparams == NULL) {
Py_DECREF(parameters);
Py_XDECREF(tuple_args);
return NULL;
goto error;
}
}
if (subparams && PyTuple_Check(subparams)) {
Expand All @@ -243,7 +241,7 @@ _Py_make_parameters(PyObject *args)
if (_PyTuple_Resize(&parameters, len) < 0) {
Py_DECREF(subparams);
Py_XDECREF(tuple_args);
return NULL;
goto cleanup;
}
}
for (Py_ssize_t j = 0; j < len2; j++) {
Expand All @@ -256,13 +254,19 @@ _Py_make_parameters(PyObject *args)
}
if (iparam < len) {
if (_PyTuple_Resize(&parameters, iparam) < 0) {
Py_XDECREF(parameters);
Py_XDECREF(tuple_args);
return NULL;
goto error;
}
}
Py_XDECREF(tuple_args);
Py_LeaveRecursiveCall();
return parameters;

error:
Py_XDECREF(parameters);
Py_XDECREF(tuple_args);
cleanup:
Py_LeaveRecursiveCall();
return NULL;
}

/* If obj is a generic alias, substitute type variables params
Expand Down
Loading