gh-132713: Fix repr(list) race condition (#132801)
Hold a strong reference to the item while calling repr(item).
This commit is contained in:
parent
722c501dba
commit
a4ea80d523
@ -118,6 +118,19 @@ class ListTest(list_tests.CommonTest):
|
||||
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):
|
||||
|
@ -0,0 +1,2 @@
|
||||
Fix ``repr(list)`` race condition: hold a strong reference to the item while
|
||||
calling ``repr(item)``. Patch by Victor Stinner.
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user