From: Sam Gross Date: Sat, 14 Sep 2024 02:02:27 +0000 (-0400) Subject: gh-124068: Fix reference leak with generators in the free-threaded build (#124069) X-Git-Tag: v3.14.0a1~474 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b02301fa5a543266ee310a6d98278d2b8e26d7b3;p=thirdparty%2FPython%2Fcpython.git gh-124068: Fix reference leak with generators in the free-threaded build (#124069) If the generator is already cleared, then most fields in the generator's frame are not valid other than f_executable. The invalid fields may contain dangling pointers and should not be used. --- diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index e981f87401a0..c645f1b9a638 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -186,7 +186,20 @@ frame_disable_deferred_refcounting(_PyInterpreterFrame *frame) // Convert locals, variables, and the executable object to strong // references from (possibly) deferred references. assert(frame->stackpointer != NULL); + assert(frame->owner == FRAME_OWNED_BY_FRAME_OBJECT || + frame->owner == FRAME_OWNED_BY_GENERATOR); + frame->f_executable = PyStackRef_AsStrongReference(frame->f_executable); + + if (frame->owner == FRAME_OWNED_BY_GENERATOR) { + PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); + if (gen->gi_frame_state == FRAME_CLEARED) { + // gh-124068: if the generator is cleared, then most fields other + // than f_executable are not valid. + return; + } + } + for (_PyStackRef *ref = frame->localsplus; ref < frame->stackpointer; ref++) { if (!PyStackRef_IsNull(*ref) && PyStackRef_IsDeferred(*ref)) { *ref = PyStackRef_AsStrongReference(*ref);