Skip to content

gh-148891: prevent crash in HAMT#148928

Draft
KowalskiThomas wants to merge 1 commit intopython:mainfrom
KowalskiThomas:kowalski/fix-prevent-crash-in-hamt
Draft

gh-148891: prevent crash in HAMT#148928
KowalskiThomas wants to merge 1 commit intopython:mainfrom
KowalskiThomas:kowalski/fix-prevent-crash-in-hamt

Conversation

@KowalskiThomas
Copy link
Copy Markdown
Contributor

@KowalskiThomas KowalskiThomas commented Apr 23, 2026

What is this PR?

Fix for the crash reported and investigated in #148891.

_PyHamt_Assoc allocates HAMT nodes, which can trigger GC. A weakref callback or finaliser fired during GC could re-enter contextvar_set, replacing ctx->ctx_vars via Py_SETREF and freeing the old HAMT while _PyHamt_Assoc was still traversing it, causing a use-after-free.

The proposed fix is to hold a strong reference to ctx->ctx_vars during the _PyHamt_Assoc call, so that a re-entrant free cannot affect the HAMT being traversed.

Comment thread Python/context.c
Comment on lines +794 to +803
// gh-148891: _PyHamt_Assoc can allocate HAMT nodes, which may trigger
// GC. A weakref callback or finalizer could then re-enter
// contextvar_set, replacing ctx->ctx_vars via Py_SETREF and freeing
// the old HAMT while _PyHamt_Assoc is still traversing it.
// Prevent this by holding a strong reference to the current vars.
PyHamtObject *old_vars = ctx->ctx_vars;
Py_INCREF(old_vars);
PyHamtObject *new_vars = _PyHamt_Assoc(
ctx->ctx_vars, (PyObject *)var, val);
old_vars, (PyObject *)var, val);
Py_DECREF(old_vars);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks true. We have a lot of increfs/decrefs like that because the call between them can do scary things.

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.

2 participants