gh-143100: Fix memcpy data race in setobject.c (gh-143127)

This commit is contained in:
Sam Gross 2025-12-24 08:02:19 -05:00 committed by GitHub
parent 4ee6929d60
commit e8e044eda3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 16 additions and 3 deletions

View file

@ -1420,6 +1420,17 @@ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return make_new_set(type, NULL);
}
#ifdef Py_GIL_DISABLED
static void
copy_small_table(setentry *dest, setentry *src)
{
for (Py_ssize_t i = 0; i < PySet_MINSIZE; i++) {
_Py_atomic_store_ptr_release(&dest[i].key, src[i].key);
_Py_atomic_store_ssize_relaxed(&dest[i].hash, src[i].hash);
}
}
#endif
/* set_swap_bodies() switches the contents of any two sets by moving their
internal data pointers and, if needed, copying the internal smalltables.
Semantically equivalent to:
@ -1462,8 +1473,13 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
if (a_table == a->smalltable || b_table == b->smalltable) {
memcpy(tab, a->smalltable, sizeof(tab));
#ifndef Py_GIL_DISABLED
memcpy(a->smalltable, b->smalltable, sizeof(tab));
memcpy(b->smalltable, tab, sizeof(tab));
#else
copy_small_table(a->smalltable, b->smalltable);
copy_small_table(b->smalltable, tab);
#endif
}
if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type) &&

View file

@ -20,6 +20,3 @@ thread:pthread_create
# PyObject_Realloc internally does memcpy which isn't atomic so can race
# with non-locking reads. See #132070
race:PyObject_Realloc
# gh-143100: set_swap_bodies in setobject.c calls memcpy, which isn't atomic
race:set_swap_bodies