From 3f08b30ab334a1b3f40b3c185ddd5391e83636b1 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 22 Oct 2026 14:50:54 -0700 Subject: [PATCH] gh-159739: Protect list storage while reporting its size (GH-160196) On free-threaded builds, list.__sizeof__() reads an allocation header through an atomically loaded storage pointer. The list's owner can resize and free that storage between the load and the header read, producing invalid size data or an invalid memory read. Hold the list lock while inspecting the allocation. Backport to 3.15 and 3.14. (cherry picked from commit d98f2cba6131b72a8762a64f4f7af19706beb966) Co-authored-by: Jelle Zijlstra --- .../2026-10-21-21-26-10.gh-issue-159739.Aw61LR.rst | 1 + Objects/listobject.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-10-21-21-26-10.gh-issue-159739.Aw61LR.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-21-21-26-10.gh-issue-159739.Aw61LR.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-21-21-26-10.gh-issue-159739.Aw61LR.rst new file mode 100644 index 000000000000000..5de64814b1ca55d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-21-21-26-10.gh-issue-159739.Aw61LR.rst @@ -0,0 +1 @@ +Fix a race in ``list.__sizeof__()`` when a list is concurrently resized on a free-threaded build. diff --git a/Objects/listobject.c b/Objects/listobject.c index b6ebb2b53fc3044..c09d4618551e12a 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3602,10 +3602,12 @@ list___sizeof___impl(PyListObject *self) { size_t res = _PyObject_SIZE(Py_TYPE(self)); #ifdef Py_GIL_DISABLED - PyObject **ob_item = _Py_atomic_load_ptr(&self->ob_item); + Py_BEGIN_CRITICAL_SECTION(self); + PyObject **ob_item = self->ob_item; if (ob_item != NULL) { res += list_capacity(ob_item) * sizeof(PyObject *); } + Py_END_CRITICAL_SECTION(); #else res += (size_t)self->allocated * sizeof(PyObject *); #endif