From 5b3b3f51681584bc1a83ac146c864fa3d054585f Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sun, 11 Jan 2026 01:47:57 +0300 Subject: [PATCH 1/3] gh-143635: Fix crash in `_Py_typing_type_repr` --- Lib/test/test_genericalias.py | 37 +++++++++++++++++++++++++++++++++++ Objects/typevarobject.c | 5 ++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 9df9296e26ad5c..aaabd6ca567580 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -244,6 +244,43 @@ class MyGeneric: self.assertEndsWith(repr(MyGeneric[[]]), 'MyGeneric[[]]') self.assertEndsWith(repr(MyGeneric[[int, str]]), 'MyGeneric[[int, str]]') + def test_evil_repr1(self): + # gh-143635 + class Zap: + def __init__(self, container): + self.container = container + def __getattr__(self, name): + if name == "__origin__": + self.container.clear() + return None + if name == "__args__": + return () + raise AttributeError + + params = [] + params.append(Zap(params)) + alias = type(list[int])(list, (params,)) + repr_str = repr(alias) + self.assertTrue(repr_str.startswith("list[["), repr_str) + + def test_evil_repr2(self): + class Zap: + def __init__(self, container): + self.container = container + def __getattr__(self, name): + if name == "__qualname__": + self.container.clear() + return "abcd" + if name == "__module__": + return None + raise AttributeError + + params = [] + params.append(Zap(params)) + alias = type(list[int])(list, (params,)) + repr_str = repr(alias) + self.assertTrue(repr_str.startswith("list[["), repr_str) + def test_exposed_type(self): import types a = types.GenericAlias(list, int) diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 2ec546aff52c0a..94b2fa3e16d100 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -270,13 +270,14 @@ _Py_typing_type_repr(PyUnicodeWriter *writer, PyObject *p) if (p == Py_Ellipsis) { // The Ellipsis object r = PyUnicode_FromString("..."); - goto exit; + goto cleanup; } if (p == (PyObject *)&_PyNone_Type) { return PyUnicodeWriter_WriteASCII(writer, "None", 4); } + Py_INCREF(p); // gh-143635 if ((rc = PyObject_HasAttrWithError(p, &_Py_ID(__origin__))) > 0 && (rc = PyObject_HasAttrWithError(p, &_Py_ID(__args__))) > 0) { @@ -316,6 +317,8 @@ _Py_typing_type_repr(PyUnicodeWriter *writer, PyObject *p) use_repr: r = PyObject_Repr(p); exit: + Py_DECREF(p); // gh-143635 +cleanup: Py_XDECREF(qualname); Py_XDECREF(module); if (r == NULL) { From 0eee5b8a9c05c7ce0a0a45e3273e97faeffac2ec Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sun, 11 Jan 2026 20:11:43 +0300 Subject: [PATCH 2/3] gh-143635: Fix crash in `_Py_typing_type_repr` --- .../2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst new file mode 100644 index 00000000000000..167bd80e180f0a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst @@ -0,0 +1 @@ +Fixes a crash in ``_Py_typing_type_repr`` function. From 4e08352103ecb6c8a81b8d32d046153c40f3c3a9 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 14 Jan 2026 11:15:12 +0300 Subject: [PATCH 3/3] Fix the third crash --- Lib/test/test_genericalias.py | 17 +++++++++++++++-- ...26-01-11-20-11-36.gh-issue-143670.klnGoD.rst | 2 +- Objects/genericaliasobject.c | 7 ++++++- Objects/typevarobject.c | 5 +---- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index aaabd6ca567580..2f0d929900e9fe 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -259,7 +259,7 @@ def __getattr__(self, name): params = [] params.append(Zap(params)) - alias = type(list[int])(list, (params,)) + alias = GenericAlias(list, (params,)) repr_str = repr(alias) self.assertTrue(repr_str.startswith("list[["), repr_str) @@ -277,10 +277,23 @@ def __getattr__(self, name): params = [] params.append(Zap(params)) - alias = type(list[int])(list, (params,)) + alias = GenericAlias(list, (params,)) repr_str = repr(alias) self.assertTrue(repr_str.startswith("list[["), repr_str) + def test_evil_repr3(self): + # gh-143823 + lst = [] + class X: + def __repr__(self): + lst.clear() + return "x" + + lst += [X(), 1] + ga = GenericAlias(int, lst) + with self.assertRaises(IndexError): + repr(ga) + def test_exposed_type(self): import types a = types.GenericAlias(list, int) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst index 167bd80e180f0a..4ce0e71a47e145 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-11-20-11-36.gh-issue-143670.klnGoD.rst @@ -1 +1 @@ -Fixes a crash in ``_Py_typing_type_repr`` function. +Fixes a crash in ``ga_repr_items_list`` function. diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 8b526f43f1e053..119dd4b5c2dd00 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -68,10 +68,15 @@ ga_repr_items_list(PyUnicodeWriter *writer, PyObject *p) return -1; } } - PyObject *item = PyList_GET_ITEM(p, i); + PyObject *item = PyList_GetItemRef(p, i); + if (item == NULL) { + return -1; // list can be mutated in a callback + } if (_Py_typing_type_repr(writer, item) < 0) { + Py_DECREF(item); return -1; } + Py_DECREF(item); } if (PyUnicodeWriter_WriteChar(writer, ']') < 0) { diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 94b2fa3e16d100..2ec546aff52c0a 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -270,14 +270,13 @@ _Py_typing_type_repr(PyUnicodeWriter *writer, PyObject *p) if (p == Py_Ellipsis) { // The Ellipsis object r = PyUnicode_FromString("..."); - goto cleanup; + goto exit; } if (p == (PyObject *)&_PyNone_Type) { return PyUnicodeWriter_WriteASCII(writer, "None", 4); } - Py_INCREF(p); // gh-143635 if ((rc = PyObject_HasAttrWithError(p, &_Py_ID(__origin__))) > 0 && (rc = PyObject_HasAttrWithError(p, &_Py_ID(__args__))) > 0) { @@ -317,8 +316,6 @@ _Py_typing_type_repr(PyUnicodeWriter *writer, PyObject *p) use_repr: r = PyObject_Repr(p); exit: - Py_DECREF(p); // gh-143635 -cleanup: Py_XDECREF(qualname); Py_XDECREF(module); if (r == NULL) {