]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-128759: Fix accesses to `tp_version_tag`. (GH-129750)
authorSam Gross <colesbury@gmail.com>
Wed, 12 Feb 2025 14:34:40 +0000 (09:34 -0500)
committerGitHub <noreply@github.com>
Wed, 12 Feb 2025 14:34:40 +0000 (09:34 -0500)
We should use a relaxed atomic load in the free threading build in
`PyType_Modified()` because that's called without the type lock held.
It's not necessary to use atomics in `type_modified_unlocked()`.

We should also use `FT_ATOMIC_STORE_UINT_RELAXED()` instead of the
`UINT32` variant because `tp_version_tag` is declared as `unsigned int`.

Objects/typeobject.c

index 59ea2e3331ff54693ebeba0a6e5cd83f92825f70..1484d9b33417b2bdfb78e4d8a2b05bfc7af0181d 100644 (file)
@@ -1010,7 +1010,7 @@ set_version_unlocked(PyTypeObject *tp, unsigned int version)
         _Py_atomic_add_uint16(&tp->tp_versions_used, 1);
     }
 #endif
-    FT_ATOMIC_STORE_UINT32_RELAXED(tp->tp_version_tag, version);
+    FT_ATOMIC_STORE_UINT_RELAXED(tp->tp_version_tag, version);
 #ifndef Py_GIL_DISABLED
     if (version != 0) {
         PyTypeObject **slot =
@@ -1039,7 +1039,8 @@ type_modified_unlocked(PyTypeObject *type)
        We don't assign new version tags eagerly, but only as
        needed.
      */
-    if (FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag) == 0) {
+    ASSERT_TYPE_LOCK_HELD();
+    if (type->tp_version_tag == 0) {
         return;
     }
     // Cannot modify static builtin types.
@@ -1094,7 +1095,7 @@ void
 PyType_Modified(PyTypeObject *type)
 {
     // Quick check without the lock held
-    if (type->tp_version_tag == 0) {
+    if (FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag) == 0) {
         return;
     }