]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-131113: Fix data race in dict.popitem() (gh-131115) (#131119)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 11 Mar 2025 23:39:29 +0000 (00:39 +0100)
committerGitHub <noreply@github.com>
Tue, 11 Mar 2025 23:39:29 +0000 (23:39 +0000)
The clearing of the key, hash, and value need to use atomic operations
to avoid a data race with concurrent read operations.
(cherry picked from commit c00ac578241b3213ceb79c1f32bc83ea471f02da)

Co-authored-by: Sam Gross <colesbury@gmail.com>
Objects/dictobject.c

index fd8453c5d9968dc29f3af3d476a8d84e1ef67d7f..680d6beb76057182dc0929d412662cce855ffa9e 100644 (file)
@@ -275,10 +275,10 @@ load_keys_nentries(PyDictObject *mp)
 
 #endif
 
-#define STORE_KEY(ep, key) FT_ATOMIC_STORE_PTR_RELEASE(ep->me_key, key)
-#define STORE_VALUE(ep, value) FT_ATOMIC_STORE_PTR_RELEASE(ep->me_value, value)
+#define STORE_KEY(ep, key) FT_ATOMIC_STORE_PTR_RELEASE((ep)->me_key, key)
+#define STORE_VALUE(ep, value) FT_ATOMIC_STORE_PTR_RELEASE((ep)->me_value, value)
 #define STORE_SPLIT_VALUE(mp, idx, value) FT_ATOMIC_STORE_PTR_RELEASE(mp->ma_values->values[idx], value)
-#define STORE_HASH(ep, hash) FT_ATOMIC_STORE_SSIZE_RELAXED(ep->me_hash, hash)
+#define STORE_HASH(ep, hash) FT_ATOMIC_STORE_SSIZE_RELAXED((ep)->me_hash, hash)
 #define STORE_KEYS_USABLE(keys, usable) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_usable, usable)
 #define STORE_KEYS_NENTRIES(keys, nentries) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_nentries, nentries)
 #define STORE_USED(mp, used) FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, used)
@@ -4465,8 +4465,8 @@ dict_popitem_impl(PyDictObject *self)
                 interp, PyDict_EVENT_DELETED, self, key, NULL);
         hash = unicode_get_hash(key);
         value = ep0[i].me_value;
-        ep0[i].me_key = NULL;
-        ep0[i].me_value = NULL;
+        STORE_KEY(&ep0[i], NULL);
+        STORE_VALUE(&ep0[i], NULL);
     }
     else {
         PyDictKeyEntry *ep0 = DK_ENTRIES(self->ma_keys);
@@ -4481,9 +4481,9 @@ dict_popitem_impl(PyDictObject *self)
                 interp, PyDict_EVENT_DELETED, self, key, NULL);
         hash = ep0[i].me_hash;
         value = ep0[i].me_value;
-        ep0[i].me_key = NULL;
-        ep0[i].me_hash = -1;
-        ep0[i].me_value = NULL;
+        STORE_KEY(&ep0[i], NULL);
+        STORE_HASH(&ep0[i], -1);
+        STORE_VALUE(&ep0[i], NULL);
     }
 
     j = lookdict_index(self->ma_keys, hash, i);