From d2f1fb3bf906667b5a2f22349ffe77021dd4ab35 Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sun, 17 May 2026 18:39:20 -0400 Subject: [PATCH 1/4] Update _elementtree.c --- Modules/_elementtree.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 9e794be5c109ba..c9528500bc2215 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1863,6 +1863,34 @@ element_subscr(PyObject *op, PyObject *item) } } +// Pointer-by-pointer memmove for PyObject** arrays that is safe +// for shared ElementObjects in Py_GIL_DISABLED builds. +static void +ptr_wise_atomic_memmove(ElementObject *a, PyObject **dest, PyObject **src, Py_ssize_t n) +{ +#ifndef Py_GIL_DISABLED + memmove(dest, src, n * sizeof(PyObject *)); +#else + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(a); + if (_Py_IsOwnedByCurrentThread((PyObject *)a) && !_PyObject_GC_IS_SHARED(a)) { + // No other threads can read this list concurrently + memmove(dest, src, n * sizeof(PyObject *)); + return; + } + if (dest < src) { + for (Py_ssize_t i = 0; i != n; i++) { + _Py_atomic_store_ptr_release(&dest[i], src[i]); + } + } + else { + // copy backwards to avoid overwriting src before it's read + for (Py_ssize_t i = n; i != 0; i--) { + _Py_atomic_store_ptr_release(&dest[i - 1], src[i - 1]); + } + } +#endif +} + static int element_ass_subscr(PyObject *op, PyObject *item, PyObject *value) { @@ -1938,19 +1966,21 @@ element_ass_subscr(PyObject *op, PyObject *item, PyObject *value) PyList_SET_ITEM(recycle, i, self->extra->children[cur]); - memmove( + ptr_wise_atomic_memmove( + self, self->extra->children + cur - i, self->extra->children + cur + 1, - num_moved * sizeof(PyObject *)); + num_moved); } /* Leftover "tail" after the last removed child */ cur = start + (size_t)slicelen * step; if (cur < (size_t)self->extra->length) { - memmove( + ptr_wise_atomic_memmove( + self, self->extra->children + cur - slicelen, self->extra->children + cur, - (self->extra->length - cur) * sizeof(PyObject *)); + self->extra->length - cur); } self->extra->length -= slicelen; From 870d3a39d65c6cf9cb71a15ce92c4515d3adf2f7 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 22:42:57 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst diff --git a/Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst b/Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst new file mode 100644 index 00000000000000..ea8eac20e4c8ec --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst @@ -0,0 +1 @@ +WIthin ``Modules/_elementtree.c``, improve thread-safety in ElementObjects within ``element_ass_subscr`` From d9cc016fabc3313559531bc52102ee28e79d24a8 Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sun, 17 May 2026 18:59:10 -0400 Subject: [PATCH 3/4] Modify critical section assertion in _elementtree.c Commented out critical section assertion for ElementObject. --- Modules/_elementtree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index c9528500bc2215..0e60e131acc991 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1871,7 +1871,8 @@ ptr_wise_atomic_memmove(ElementObject *a, PyObject **dest, PyObject **src, Py_ss #ifndef Py_GIL_DISABLED memmove(dest, src, n * sizeof(PyObject *)); #else - _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(a); + // XXX: maybe a critical section isn't needed for ElementObject? + // _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(a); if (_Py_IsOwnedByCurrentThread((PyObject *)a) && !_PyObject_GC_IS_SHARED(a)) { // No other threads can read this list concurrently memmove(dest, src, n * sizeof(PyObject *)); From 4264d5491fd47f7010172edfb4cbe0fa890e747a Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Mon, 18 May 2026 06:35:58 -0400 Subject: [PATCH 4/4] Update Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst Co-authored-by: Sergey Miryanov --- .../next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst b/Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst index ea8eac20e4c8ec..99d9a06988bb31 100644 --- a/Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst +++ b/Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.OFW3ZD.rst @@ -1 +1 @@ -WIthin ``Modules/_elementtree.c``, improve thread-safety in ElementObjects within ``element_ass_subscr`` +Improve thread-safety of ElementObjects in ``element_ass_subscr``