Skip to content

Race condition in _Py_ExplicitMergeRefcount #119999

Closed
@colesbury

Description

@colesbury

Bug report

There is a subtle possible race condition in _Py_ExplicitMergeRefcount: we set ob_ref_local and ob_tid to zero after writing the merged refcount to ob_ref_shared.

That's not safe, because another thread might possibly deallocate the object after we merged refcount. For example:

  • Assume that the merged refcount is 1
  • Some other thread calls Py_DECREF() and immediately frees the object
  • We write zero to ob_ref_local and ob_tid -- BUG!

cpython/Objects/object.c

Lines 413 to 422 in 41c1cef

} while (!_Py_atomic_compare_exchange_ssize(&op->ob_ref_shared,
&shared, new_shared));
#ifdef Py_REF_DEBUG
_Py_AddRefTotal(_PyThreadState_GET(), extra);
#endif
_Py_atomic_store_uint32_relaxed(&op->ob_ref_local, 0);
_Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
return refcnt;

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixes3.14new features, bugs and security fixestopic-free-threadingtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions