Skip to content

Protect getlist() walk with a critical section (free-threading, #9852) - #9854

Open
espressolee wants to merge 1 commit into
python-pillow:mainfrom
espressolee:ft-getlist-critical-section
Open

Protect getlist() walk with a critical section (free-threading, #9852)#9854
espressolee wants to merge 1 commit into
python-pillow:mainfrom
espressolee:ft-getlist-critical-section

Conversation

@espressolee

@espressolee espressolee commented Aug 5, 2026

Copy link
Copy Markdown

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.

Fixes #9852.

🤖 Generated with Claude Code

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>
@radarhere radarhere added the Free-threading PEP 703 support label Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Free-threading PEP 703 support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Free-threaded: Image.point(list) crashes if another thread mutates the list (getlist / PySequence_Fast, stale size)

2 participants