From a5f3cf7cb845a00cba536596b5a9280c71b7fe73 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Mon, 6 Apr 2026 00:23:07 +0100 Subject: [PATCH] gh-148144: Initialize visited on copied interpreter frames (GH-148143) _PyFrame_Copy() copied interpreter frames into generator and frame-object storage without initializing the visited byte. Incremental GC later reads frame->visited in mark_stacks() on non-start passes, so copied frames could expose an uninitialized value once they became live on a thread stack again. Reset visited when copying a frame so copied frames start with defined GC bookkeeping state. Preserve lltrace in Py_DEBUG builds. (cherry picked from commit fbfc6ccb0abf362a0ecdc02cd0aa2d16c1a4ce44) Co-authored-by: Pablo Galindo Salgado --- Include/internal/pycore_interpframe.h | 5 +++++ .../2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst diff --git a/Include/internal/pycore_interpframe.h b/Include/internal/pycore_interpframe.h index 19914e8cef7ed2..b5b729f141bab5 100644 --- a/Include/internal/pycore_interpframe.h +++ b/Include/internal/pycore_interpframe.h @@ -149,6 +149,11 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame * int stacktop = (int)(src->stackpointer - src->localsplus); assert(stacktop >= 0); dest->stackpointer = dest->localsplus + stacktop; + // visited is GC bookkeeping for the current stack walk, not frame state. + dest->visited = 0; +#ifdef Py_DEBUG + dest->lltrace = src->lltrace; +#endif for (int i = 0; i < stacktop; i++) { dest->localsplus[i] = PyStackRef_MakeHeapSafe(src->localsplus[i]); } diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst new file mode 100644 index 00000000000000..beda992a95bf94 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst @@ -0,0 +1,3 @@ +Initialize ``_PyInterpreterFrame.visited`` when copying interpreter frames so +incremental GC does not read an uninitialized byte from generator and +frame-object copies.