gh-151627: protect OrderedDict iterator creation by pedramkarimii · Pull Request #151688 · python/cpython · GitHub
Skip to content

gh-151627: protect OrderedDict iterator creation - #151688

Merged
kumaraditya303 merged 1 commit into
python:mainfrom
pedramkarimii:gh-151627-odict-iterator-race
Aug 1, 2026
Merged

gh-151627: protect OrderedDict iterator creation#151688
kumaraditya303 merged 1 commit into
python:mainfrom
pedramkarimii:gh-151627-odict-iterator-race

Conversation

@pedramkarimii

Copy link
Copy Markdown
Contributor

Fixes gh-151627.

In free-threaded builds, OrderedDict iterator creation could read the ordered linked-list head/tail, the current node key, the size, and od_state without holding the OrderedDict critical section. A concurrent clear() or update() could mutate or free the linked-list nodes while odictiter_new() was taking that initial iterator snapshot, leading to a data race and a crash/use-after-free.

This change protects the initial iterator snapshot in odictiter_new() with the OrderedDict critical section. The mutation paths already update the linked-list state while holding the OrderedDict lock, so taking the iterator's initial current key, size, state, and object reference under the same critical section avoids racing with concurrent clear()/update().

This is separate from gh-151633/gh-151634, which address Counter.update() in _collectionsmodule.c. This PR targets OrderedDict iterator construction in Objects/odictobject.c.

A free-threading regression test was added that repeatedly creates forward and reversed OrderedDict iterators while another thread concurrently clears and updates the same OrderedDict.

Tests run:

./python -m test test_free_threading.test_collections -v
./python -m test test_free_threading.test_collections -v -m test_iterator_update_clear_race
./python -m test test_ordered_dict -v
./python ../gh151627_reproducer.py

@pedramkarimii

Copy link
Copy Markdown
Contributor Author

@python-cla-bot

python-cla-bot Bot commented Jun 20, 2026

Copy link
Copy Markdown

@pedramkarimii
pedramkarimii force-pushed the gh-151627-odict-iterator-race branch from 4762cdd to ba229fd Compare June 20, 2026 04:22
@kumaraditya303
kumaraditya303 merged commit 86dab7c into python:main Aug 1, 2026
107 of 109 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash (use-after-free) in odictiter_new when an OrderedDict is concurrently iterated and updated/cleared

2 participants