[3.14] gh-148144: Initialize visited on copied interpreter frames (GH-148143) (#148147)

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 fbfc6ccb0a)

Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
This commit is contained in:
Miss Islington (bot) 2026-04-06 01:49:47 +02:00 committed by GitHub
parent e99b801aeb
commit 636946f413
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 8 additions and 0 deletions

View 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]);
}

View file

@ -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.