https://github.com/python/cpython/commit/fbfc6ccb0abf362a0ecdc02cd0aa2d16c1a4ce44
commit: fbfc6ccb0abf362a0ecdc02cd0aa2d16c1a4ce44
branch: main
author: Pablo Galindo Salgado <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-04-06T00:23:07+01:00
summary:
gh-148144: Initialize visited on copied interpreter frames (#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.
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst
M Include/internal/pycore_interpframe.h
diff --git a/Include/internal/pycore_interpframe.h
b/Include/internal/pycore_interpframe.h
index 8db1aebdc11401..d744dd12cd0479 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.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]