Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3de0f55

Browse filesBrowse files
authored
[3.13] gh-132713: Fix repr(list) race condition (#132801) (#132809)
Hold a strong reference to the item while calling repr(item). (cherry picked from commit a4ea80d)
1 parent 3a130c1 commit 3de0f55
Copy full SHA for 3de0f55

File tree

Expand file treeCollapse file tree

3 files changed

+22
-1
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+22
-1
lines changed

‎Lib/test/test_list.py

Copy file name to clipboardExpand all lines: Lib/test/test_list.py
+13Lines 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):
+2Lines 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

Copy file name to clipboardExpand all lines: Objects/listobject.c
+7-1Lines changed: 7 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,15 @@ 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+
/* Hold a strong reference since repr(item) can mutate the list */
606+
item = Py_NewRef(v->ob_item[i]);
607+
604608
if (i > 0) {
605609
if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)
606610
goto error;
607611
}
608612

609-
s = PyObject_Repr(v->ob_item[i]);
613+
s = PyObject_Repr(item);
610614
if (s == NULL)
611615
goto error;
612616

@@ -615,6 +619,7 @@ list_repr_impl(PyListObject *v)
615619
goto error;
616620
}
617621
Py_DECREF(s);
622+
Py_CLEAR(item);
618623
}
619624

620625
writer.overallocate = 0;
@@ -625,6 +630,7 @@ list_repr_impl(PyListObject *v)
625630
return _PyUnicodeWriter_Finish(&writer);
626631

627632
error:
633+
Py_XDECREF(item);
628634
_PyUnicodeWriter_Dealloc(&writer);
629635
Py_ReprLeave((PyObject *)v);
630636
return NULL;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.