https://github.com/python/cpython/commit/a4ea80d52394bafffb2257abbe815c7ffdb003a3 commit: a4ea80d52394bafffb2257abbe815c7ffdb003a3 branch: main author: Victor Stinner <vstin...@python.org> committer: vstinner <vstin...@python.org> date: 2025-04-22T22:09:35+02:00 summary:
gh-132713: Fix repr(list) race condition (#132801) Hold a strong reference to the item while calling repr(item). files: A Misc/NEWS.d/next/Core_and_Builtins/2025-04-22-16-38-43.gh-issue-132713.mBWTSZ.rst M Lib/test/test_list.py M Objects/listobject.c diff --git a/Lib/test/test_list.py b/Lib/test/test_list.py index ec65ed49281527..6894fba2ad1b00 100644 --- a/Lib/test/test_list.py +++ b/Lib/test/test_list.py @@ -118,6 +118,19 @@ def test_list_resize_overflow(self): with self.assertRaises((MemoryError, OverflowError)): lst *= size + def test_repr_mutate(self): + class Obj: + @staticmethod + def __repr__(): + try: + mylist.pop() + except IndexError: + pass + return 'obj' + + mylist = [Obj() for _ in range(5)] + self.assertEqual(repr(mylist), '[obj, obj, obj]') + def test_repr_large(self): # Check the repr of large list objects def check(n): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-22-16-38-43.gh-issue-132713.mBWTSZ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-22-16-38-43.gh-issue-132713.mBWTSZ.rst new file mode 100644 index 00000000000000..877b42374a396e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-22-16-38-43.gh-issue-132713.mBWTSZ.rst @@ -0,0 +1,2 @@ +Fix ``repr(list)`` race condition: hold a strong reference to the item while +calling ``repr(item)``. Patch by Victor Stinner. diff --git a/Objects/listobject.c b/Objects/listobject.c index 12d5b33414a92a..3f665a4929f14e 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -583,6 +583,7 @@ list_repr_impl(PyListObject *v) /* "[" + "1" + ", 2" * (len - 1) + "]" */ Py_ssize_t prealloc = 1 + 1 + (2 + 1) * (Py_SIZE(v) - 1) + 1; PyUnicodeWriter *writer = PyUnicodeWriter_Create(prealloc); + PyObject *item = NULL; if (writer == NULL) { goto error; } @@ -594,6 +595,13 @@ list_repr_impl(PyListObject *v) /* Do repr() on each element. Note that this may mutate the list, so must refetch the list size on each iteration. */ for (Py_ssize_t i = 0; i < Py_SIZE(v); ++i) { + item = list_get_item_ref(v, i); + if (item == NULL) { + // List truncated while iterating on it + PyErr_Clear(); + break; + } + if (i > 0) { if (PyUnicodeWriter_WriteChar(writer, ',') < 0) { goto error; @@ -603,9 +611,10 @@ list_repr_impl(PyListObject *v) } } - if (PyUnicodeWriter_WriteRepr(writer, v->ob_item[i]) < 0) { + if (PyUnicodeWriter_WriteRepr(writer, item) < 0) { goto error; } + Py_CLEAR(item); } if (PyUnicodeWriter_WriteChar(writer, ']') < 0) { @@ -616,6 +625,7 @@ list_repr_impl(PyListObject *v) return PyUnicodeWriter_Finish(writer); error: + Py_XDECREF(item); PyUnicodeWriter_Discard(writer); Py_ReprLeave((PyObject *)v); return NULL; _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com