Skip to content

Three sites still truncate frameNames alone, drifting it from frameCrefs and frameMethods #651

Open

Description

@tannevaled

The VM keeps three parallel frame stacks — frameNames, frameCrefs, frameMethods — that mirror each other one for one. Index i means the same frame in all three only while they are the same length. exec pushes and pops them together, and every unwind restores them together.

Four sites truncate frameNames alone. One was fixed in #649; three remain:

site trigger
internal/vm/find.go:153 (findYield) Find.prune inside Find.find
internal/vm/irb_bind.go:65 any exception raised in an IRB statement
internal/vm/pstore.go:366 PStore#transaction with #commit / #abort

This is reachable from Ruby, not latent

It went unnoticed for as long as backtraces read frameNames alone. Since #645 gave the VM a line map and #649 made frameLabel read all three stacks, one leaked entry makes every later label some other frame's — the labels silently name the wrong methods from that point on.

The shape is the problem

Three slices kept in step by hand, with no type making the invariant hold, will drift again: this is the fourth site found, and nothing prevents a fifth. One slice of a frame struct — name, cref and method together — would make the invariant unrepresentable to violate, which is the standing preference for this codebase (see make-the-illegal-state-unrepresentable-in-go).

Doing that is larger than any one of the three fixes and touches exec's hot path, so it wants measuring: the frame push/pop is on every call. Worth a wave of its own rather than a patch.

Found by the agent that landed #649, which named all four sites and fixed the one in its own file set.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions