From 16b98b1d1cce4580fb62a59e797f4e225a014e58 Mon Sep 17 00:00:00 2001 From: Bhuvansh Kataria Date: Sat, 1 Aug 2026 19:32:49 +0000 Subject: [PATCH 1/5] gh-155053: Fix GenericAlias crash on OOM --- Lib/test/test_genericalias.py | 29 ++++++++++++++++++- ...-08-01-19-17-56.gh-issue-155053.sxmlTO.rst | 2 ++ Objects/genericaliasobject.c | 1 - 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 7816775620bc013..32cfbf6cfe5fbc4 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -1,6 +1,8 @@ """Tests for C-implemented GenericAlias.""" import unittest +from test import support +from test.support import import_helper import pickle from array import array import copy @@ -62,10 +64,11 @@ from string.templatelib import Template, Interpolation import typing -from typing import TypeVar, Unpack +from typing import TypeVar, TypeVarTuple, Unpack T = TypeVar('T') K = TypeVar('K') V = TypeVar('V') +Ts = TypeVarTuple("Ts") _UNPACKED_TUPLES = [ # Unpacked tuple using `*` @@ -97,6 +100,7 @@ tuple[*tuple[Unpack[tuple[int, ...]]]], ] +_testcapi = import_helper.import_module("_testcapi") class BaseTest(unittest.TestCase): """Test basics.""" @@ -628,6 +632,29 @@ def test_gh150146(self): with self.assertRaises(TypeError): x[*typing.Mapping[..., ...]] + @support.nomemtest + def test_subs_tvars_nomemory(self): + alias = dict[str, tuple[*Ts]] + key = (int, str) + + # Warm the code path to stabilize the allocation window. + # This injection point was determined experimentally for this build. + try: + dict[str, tuple[int, str]] + except Exception: + pass + + _testcapi.set_nomemory(24, 25) + raised = False + try: + alias[key] + except MemoryError: + raised = True + finally: + _testcapi.remove_mem_hooks() + + self.assertTrue(raised, "MemoryError not raised") + class TypeIterationTests(unittest.TestCase): _UNITERABLE_TYPES = (list, tuple) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst new file mode 100644 index 000000000000000..a0e0d787794e094 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst @@ -0,0 +1,2 @@ +Fix a crash in :class:`types.GenericAlias` when ``tuple_extend()`` fails +during substitution of a ``TypeVarTuple`` under allocation failure. diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 348c7dd6967a397..5cb1686fdbf8e27 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -302,7 +302,6 @@ subs_tvars(PyObject *obj, PyObject *params, PyTuple_GET_SIZE(arg)); if (j < 0) { Py_DECREF(subparams); - Py_DECREF(subargs); return NULL; } continue; From 753c30b414accf82966df8f8e8690441b40e0021 Mon Sep 17 00:00:00 2001 From: Bhuvansh Kataria Date: Sun, 2 Aug 2026 13:24:12 +0000 Subject: [PATCH 2/5] gh-155053: Address review comments --- Lib/test/test_genericalias.py | 30 +----------------------------- Objects/genericaliasobject.c | 2 ++ 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 32cfbf6cfe5fbc4..e508bcb79f5d41c 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -1,8 +1,6 @@ """Tests for C-implemented GenericAlias.""" import unittest -from test import support -from test.support import import_helper import pickle from array import array import copy @@ -64,11 +62,10 @@ from string.templatelib import Template, Interpolation import typing -from typing import TypeVar, TypeVarTuple, Unpack +from typing import TypeVar, Unpack T = TypeVar('T') K = TypeVar('K') V = TypeVar('V') -Ts = TypeVarTuple("Ts") _UNPACKED_TUPLES = [ # Unpacked tuple using `*` @@ -100,8 +97,6 @@ tuple[*tuple[Unpack[tuple[int, ...]]]], ] -_testcapi = import_helper.import_module("_testcapi") - class BaseTest(unittest.TestCase): """Test basics.""" generic_types = [type, tuple, list, dict, frozendict, @@ -632,29 +627,6 @@ def test_gh150146(self): with self.assertRaises(TypeError): x[*typing.Mapping[..., ...]] - @support.nomemtest - def test_subs_tvars_nomemory(self): - alias = dict[str, tuple[*Ts]] - key = (int, str) - - # Warm the code path to stabilize the allocation window. - # This injection point was determined experimentally for this build. - try: - dict[str, tuple[int, str]] - except Exception: - pass - - _testcapi.set_nomemory(24, 25) - raised = False - try: - alias[key] - except MemoryError: - raised = True - finally: - _testcapi.remove_mem_hooks() - - self.assertTrue(raised, "MemoryError not raised") - class TypeIterationTests(unittest.TestCase): _UNITERABLE_TYPES = (list, tuple) diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 5cb1686fdbf8e27..292876dde91a74b 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -302,6 +302,8 @@ subs_tvars(PyObject *obj, PyObject *params, PyTuple_GET_SIZE(arg)); if (j < 0) { Py_DECREF(subparams); + /* tuple_extend() clears subargs on failure, so there is no + reference left to decref here. */ return NULL; } continue; From 7972d8ce029f6ce6a6029618dd9bca3af95bf3dc Mon Sep 17 00:00:00 2001 From: Bhuvansh Date: Sun, 2 Aug 2026 18:56:17 +0530 Subject: [PATCH 3/5] Add BaseTest class for basic tests --- Lib/test/test_genericalias.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index e508bcb79f5d41c..7816775620bc013 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -97,6 +97,7 @@ tuple[*tuple[Unpack[tuple[int, ...]]]], ] + class BaseTest(unittest.TestCase): """Test basics.""" generic_types = [type, tuple, list, dict, frozendict, From d4d6986aadb705bedf21510d64c73fea6bed3ff3 Mon Sep 17 00:00:00 2001 From: Bhuvansh Kataria Date: Sun, 2 Aug 2026 15:30:28 +0000 Subject: [PATCH 4/5] gh-155053: Address review comments --- .../2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst | 4 ++-- Objects/genericaliasobject.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst index a0e0d787794e094..d96566f87765747 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-01-19-17-56.gh-issue-155053.sxmlTO.rst @@ -1,2 +1,2 @@ -Fix a crash in :class:`types.GenericAlias` when ``tuple_extend()`` fails -during substitution of a ``TypeVarTuple`` under allocation failure. +Fix a crash in :class:`types.GenericAlias` during substitution of a +``TypeVarTuple`` under allocation failure. diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 292876dde91a74b..f3d202621c29086 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -302,8 +302,8 @@ subs_tvars(PyObject *obj, PyObject *params, PyTuple_GET_SIZE(arg)); if (j < 0) { Py_DECREF(subparams); - /* tuple_extend() clears subargs on failure, so there is no - reference left to decref here. */ + assert(subargs == NULL); + /* tuple_extend() clears subargs on failure. */ return NULL; } continue; From fab406f99bffb44818724ef18b52aa6932be354a Mon Sep 17 00:00:00 2001 From: Bhuvansh Date: Sun, 2 Aug 2026 21:24:57 +0530 Subject: [PATCH 5/5] Update genericaliasobject.c --- Objects/genericaliasobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index f3d202621c29086..52adbb395cf6bee 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -302,8 +302,8 @@ subs_tvars(PyObject *obj, PyObject *params, PyTuple_GET_SIZE(arg)); if (j < 0) { Py_DECREF(subparams); - assert(subargs == NULL); /* tuple_extend() clears subargs on failure. */ + assert(subargs == NULL); return NULL; } continue;