]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-148144: Initialize visited on copied interpreter frames (#148143)
authorPablo Galindo Salgado <Pablogsal@gmail.com>
Sun, 5 Apr 2026 23:23:07 +0000 (00:23 +0100)
committerGitHub <noreply@github.com>
Sun, 5 Apr 2026 23:23:07 +0000 (00:23 +0100)
_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.

Include/internal/pycore_interpframe.h
Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst [new file with mode: 0644]

index 8db1aebdc1140130e10e53c796ac24ab40b13587..d744dd12cd04795424645fc034c70cd9b6dfabd2 100644 (file)
@@ -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 (file)
index 0000000..beda992
--- /dev/null
@@ -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.