]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-130019: Fix data race in _PyType_AllocNoTrack (gh-130058)
authorSam Gross <colesbury@gmail.com>
Thu, 13 Feb 2025 16:50:45 +0000 (11:50 -0500)
committerGitHub <noreply@github.com>
Thu, 13 Feb 2025 16:50:45 +0000 (11:50 -0500)
The reference count fields, such as `ob_tid` and `ob_ref_shared`, may be
accessed concurrently in the free threading build by a `_Py_TryXGetRef`
or similar operation. The PyObject header fields will be initialized by
`_PyObject_Init`, so only call `memset()` to zero-initialize the remainder
of the allocation.

Objects/typeobject.c
Python/gc.c
Python/gc_free_threading.c

index 1484d9b33417b2bdfb78e4d8a2b05bfc7af0181d..818a00708b5d3d2189f1a298c281dd56c4c1e13f 100644 (file)
@@ -2251,7 +2251,9 @@ _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems)
     if (PyType_IS_GC(type)) {
         _PyObject_GC_Link(obj);
     }
-    memset(obj, '\0', size);
+    // Zero out the object after the PyObject header. The header fields are
+    // initialized by _PyObject_Init[Var]().
+    memset((char *)obj + sizeof(PyObject), 0, size - sizeof(PyObject));
 
     if (type->tp_itemsize == 0) {
         _PyObject_Init(obj, type);
index 68879b9efa14c63125ec38c8fe5228d26ae4e87d..7faf368f35898a8597bcc897c441cdd290f774fe 100644 (file)
@@ -2310,11 +2310,12 @@ PyObject *
 PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size)
 {
     size_t presize = _PyType_PreHeaderSize(tp);
-    PyObject *op = gc_alloc(tp, _PyObject_SIZE(tp) + extra_size, presize);
+    size_t size = _PyObject_SIZE(tp) + extra_size;
+    PyObject *op = gc_alloc(tp, size, presize);
     if (op == NULL) {
         return NULL;
     }
-    memset(op, 0, _PyObject_SIZE(tp) + extra_size);
+    memset((char *)op + sizeof(PyObject), 0, size - sizeof(PyObject));
     _PyObject_Init(op, tp);
     return op;
 }
index 0d6fddb5705b4a1f135577944b01c65b4f5308ff..694f97d5c57334c33e49f5eeb0b3fa3a2e021df8 100644 (file)
@@ -2595,11 +2595,12 @@ PyObject *
 PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size)
 {
     size_t presize = _PyType_PreHeaderSize(tp);
-    PyObject *op = gc_alloc(tp, _PyObject_SIZE(tp) + extra_size, presize);
+    size_t size = _PyObject_SIZE(tp) + extra_size;
+    PyObject *op = gc_alloc(tp, size, presize);
     if (op == NULL) {
         return NULL;
     }
-    memset(op, 0, _PyObject_SIZE(tp) + extra_size);
+    memset((char *)op + sizeof(PyObject), 0, size - sizeof(PyObject));
     _PyObject_Init(op, tp);
     return op;
 }