Skip to content

Commit 2edc865

Browse files
committed
pythongh-132713: Fix repr(list) race condition (python#132801)
Hold a strong reference to the item while calling repr(item). (cherry picked from commit a4ea80d)
1 parent 3a130c1 commit 2edc865

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

Lib/test/test_list.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,19 @@ def test_list_resize_overflow(self):
116116
with self.assertRaises((MemoryError, OverflowError)):
117117
lst *= size
118118

119+
def test_repr_mutate(self):
120+
class Obj:
121+
@staticmethod
122+
def __repr__():
123+
try:
124+
mylist.pop()
125+
except IndexError:
126+
pass
127+
return 'obj'
128+
129+
mylist = [Obj() for _ in range(5)]
130+
self.assertEqual(repr(mylist), '[obj, obj, obj]')
131+
119132
def test_repr_large(self):
120133
# Check the repr of large list objects
121134
def check(n):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix ``repr(list)`` race condition: hold a strong reference to the item while
2+
calling ``repr(item)``. Patch by Victor Stinner.

Objects/listobject.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,7 @@ list_repr_impl(PyListObject *v)
585585
{
586586
PyObject *s;
587587
_PyUnicodeWriter writer;
588+
PyObject *item = NULL;
588589
Py_ssize_t i = Py_ReprEnter((PyObject*)v);
589590
if (i != 0) {
590591
return i > 0 ? PyUnicode_FromString("[...]") : NULL;
@@ -601,12 +602,19 @@ list_repr_impl(PyListObject *v)
601602
/* Do repr() on each element. Note that this may mutate the list,
602603
so must refetch the list size on each iteration. */
603604
for (i = 0; i < Py_SIZE(v); ++i) {
605+
item = list_get_item_ref(v, i);
606+
if (item == NULL) {
607+
// List truncated while iterating on it
608+
PyErr_Clear();
609+
break;
610+
}
611+
604612
if (i > 0) {
605613
if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)
606614
goto error;
607615
}
608616

609-
s = PyObject_Repr(v->ob_item[i]);
617+
s = PyObject_Repr(item);
610618
if (s == NULL)
611619
goto error;
612620

@@ -615,6 +623,7 @@ list_repr_impl(PyListObject *v)
615623
goto error;
616624
}
617625
Py_DECREF(s);
626+
Py_CLEAR(item);
618627
}
619628

620629
writer.overallocate = 0;
@@ -625,6 +634,7 @@ list_repr_impl(PyListObject *v)
625634
return _PyUnicodeWriter_Finish(&writer);
626635

627636
error:
637+
Py_XDECREF(item);
628638
_PyUnicodeWriter_Dealloc(&writer);
629639
Py_ReprLeave((PyObject *)v);
630640
return NULL;

0 commit comments

Comments
 (0)