File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -791,8 +791,16 @@ contextvar_set(PyContextVar *var, PyObject *val)
791791 return -1 ;
792792 }
793793
794+ // gh-148891: _PyHamt_Assoc can allocate HAMT nodes, which may trigger
795+ // GC. A weakref callback or finalizer could then re-enter
796+ // contextvar_set, replacing ctx->ctx_vars via Py_SETREF and freeing
797+ // the old HAMT while _PyHamt_Assoc is still traversing it.
798+ // Prevent this by holding a strong reference to the current vars.
799+ PyHamtObject * old_vars = ctx -> ctx_vars ;
800+ Py_INCREF (old_vars );
794801 PyHamtObject * new_vars = _PyHamt_Assoc (
795- ctx -> ctx_vars , (PyObject * )var , val );
802+ old_vars , (PyObject * )var , val );
803+ Py_DECREF (old_vars );
796804 if (new_vars == NULL ) {
797805 return -1 ;
798806 }
@@ -819,8 +827,12 @@ contextvar_del(PyContextVar *var)
819827 return -1 ;
820828 }
821829
830+ // gh-148891: same borrowed-reference hazard as contextvar_set:
831+ // _PyHamt_Without allocates nodes, which may trigger GC re-entrancy.
822832 PyHamtObject * vars = ctx -> ctx_vars ;
833+ Py_INCREF (vars );
823834 PyHamtObject * new_vars = _PyHamt_Without (vars , (PyObject * )var );
835+ Py_DECREF (vars );
824836 if (new_vars == NULL ) {
825837 return -1 ;
826838 }
You can’t perform that action at this time.
0 commit comments