Skip to content

Commit e8e044e

Browse files
authored
gh-143100: Fix memcpy data race in setobject.c (gh-143127)
1 parent 4ee6929 commit e8e044e

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

Objects/setobject.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,17 @@ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
14201420
return make_new_set(type, NULL);
14211421
}
14221422

1423+
#ifdef Py_GIL_DISABLED
1424+
static void
1425+
copy_small_table(setentry *dest, setentry *src)
1426+
{
1427+
for (Py_ssize_t i = 0; i < PySet_MINSIZE; i++) {
1428+
_Py_atomic_store_ptr_release(&dest[i].key, src[i].key);
1429+
_Py_atomic_store_ssize_relaxed(&dest[i].hash, src[i].hash);
1430+
}
1431+
}
1432+
#endif
1433+
14231434
/* set_swap_bodies() switches the contents of any two sets by moving their
14241435
internal data pointers and, if needed, copying the internal smalltables.
14251436
Semantically equivalent to:
@@ -1462,8 +1473,13 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
14621473

14631474
if (a_table == a->smalltable || b_table == b->smalltable) {
14641475
memcpy(tab, a->smalltable, sizeof(tab));
1476+
#ifndef Py_GIL_DISABLED
14651477
memcpy(a->smalltable, b->smalltable, sizeof(tab));
14661478
memcpy(b->smalltable, tab, sizeof(tab));
1479+
#else
1480+
copy_small_table(a->smalltable, b->smalltable);
1481+
copy_small_table(b->smalltable, tab);
1482+
#endif
14671483
}
14681484

14691485
if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type) &&

Tools/tsan/suppressions_free_threading.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,3 @@ thread:pthread_create
2020
# PyObject_Realloc internally does memcpy which isn't atomic so can race
2121
# with non-locking reads. See #132070
2222
race:PyObject_Realloc
23-
24-
# gh-143100: set_swap_bodies in setobject.c calls memcpy, which isn't atomic
25-
race:set_swap_bodies

0 commit comments

Comments
 (0)