Skip to content

gh-142782: Fix use-after-free in the zoneinfo strong cache - #159441

Open
tonghuaroot wants to merge 2 commits into
python:mainfrom
tonghuaroot:zoneinfo-strong-cache-reentrant-uaf
Open

tonghuaroot wants to merge 2 commits into
python:mainfrom
tonghuaroot:zoneinfo-strong-cache-reentrant-uaf

Conversation

@tonghuaroot

Copy link
Copy Markdown
Contributor

find_in_strong_cache() compares the lookup key against each cached key with PyObject_RichCompareBool(). A str subclass whose __eq__ calls ZoneInfo.clear_cache() frees the node being compared, and the traversal then dereferences the freed node (gh-142782).

This keeps a reference to the node key during the comparison, and bumps a strong_cache_version counter on every strong-cache mutation; if the version changes during a comparison, the lookup returns a miss instead of touching a possibly-freed node. This also addresses the false-negative / duplicate concern raised on the issue.

Verified under ./configure --with-address-sanitizer: the reproducer and the new test_strong_cache_reentrant_clear crash without the fix and are clean with it; the full test_zoneinfo suite passes.

Comparing a lookup key against a cached key runs the key's __eq__, which
can re-enter and call ZoneInfo.clear_cache(), freeing the node being
compared; find_in_strong_cache() then dereferenced the freed node.

Keep a reference to the node key during the comparison and bump a cache
version counter on every mutation, so a lookup that observes a mutation
during a comparison returns a miss instead of using a freed node.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant