| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
getlist() (used by Image.point()) walks the caller's list via PySequence_Fast and the unchecked PySequence_Fast_GET_ITEM macro over a size captured earlier. On a free-threaded build a concurrent resize of that list drives an out-of-bounds read and a segfault (python-pillow#9852). Hold a critical section on the fast sequence during the walk and clamp the loop to its current length, mirroring the approach used for FontObject in python-pillow#9498. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Cross-referencing #9853 — that PR was opened before this one and it fixes the free-threading race in getlist(): wrapping getlist_impl in Py_BEGIN_CRITICAL_SECTION(arg) puts PySequence_Size inside the section as well, so the count and the walk see the same object state. Priority is @lazerg's and I am happy for that one to land instead of this. I will hold this PR open but idle rather than pushing changes to it, and follow whatever the maintainers prefer. |
Sorry, something went wrong.
|
Closing in favour of #9853, which was opened first and is the better-scoped fix. It takes the critical section on arg around the whole of getlist(), which also covers the The other half of this PR — clamping the walk to PySequence_Fast_GET_SIZE(seq) — is a separate, #9852 remains the issue of record for the race. Nothing here is lost; it is only in two better |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Fixes #9852. Alternative to #9853
getlist() (used by Image.point()) walks the caller's list with PySequence_Fast and the unchecked PySequence_Fast_GET_ITEM macro over a size captured earlier in the function. On a free-threaded build PySequence_Fast returns the list itself for a list input, so the walk aliases the caller's list; another thread resizing it drives an out-of-bounds read and a segfault. This is #9852.
This holds a critical section on the fast sequence for the walk and clamps the loop to its current length, so a resize that happened between the earlier size read and the walk cannot read out of bounds. It mirrors the critical-section approach already used for FontObject in #9498, and uses the Py_BEGIN_CRITICAL_SECTION shim already vendored in thirdparty/pythoncapi_compat.h (a no-op block on < 3.13, where the GIL serialises the walk anyway).
Verification
python3.14.0rc1t, built from source:
A concurrent resize now yields a truncated read rather than a crash; if you'd prefer it to raise instead, I'm happy to adjust.
🤖 Generated with Claude Code