gh-129967: Fix race condition in repr(set) (gh-129978)

The call to `PySequence_List()` could temporarily unlock and relock the
set, allowing the items to be cleared and return the incorrect
notation `{}` for a empty set (it should be `set()`).

Co-authored-by: T. Wouters <thomas@python.org>
This commit is contained in:
Sam Gross 2025-02-11 17:29:27 -05:00 committed by GitHub
parent 1f233f56d6
commit a7427f2db9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 54 additions and 2 deletions

View file

@ -535,9 +535,18 @@ set_repr_lock_held(PySetObject *so)
return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name);
}
keys = PySequence_List((PyObject *)so);
if (keys == NULL)
// gh-129967: avoid PySequence_List because it might re-lock the object
// lock or the GIL and allow something to clear the set from underneath us.
keys = PyList_New(so->used);
if (keys == NULL) {
goto done;
}
Py_ssize_t pos = 0, idx = 0;
setentry *entry;
while (set_next(so, &pos, &entry)) {
PyList_SET_ITEM(keys, idx++, Py_NewRef(entry->key));
}
/* repr(keys)[1:-1] */
listrepr = PyObject_Repr(keys);