Benoit Daloze 9c217d4616 Keep env chains walkable by rb_profile_frames() in vm_make_env_each()
vm_make_env_each() first escapes the parent frame, which overwrites the
flags of the parent's on-stack ep with the env object, and only then
updated the child frame to point to the parent's heap ep. If a signal
handler called rb_profile_frames() in between, as sampling profilers do,
rb_vm_frame_method_entry_unchecked() followed the child frame to the
overwritten on-stack ep, treated it as non-local and, if the parent had
no method entry (e.g. a class body), dereferenced VM_BLOCK_HANDLER_NONE
as the next ep and segfaulted.

Now the child frame is updated to point to the heap ep before the
on-stack ep of the parent is overwritten.

On x86_64 Linux with GCC 13, the new test segfaults in about half of
the runs without this change, and passed 30 out of 30 runs with it.
On macOS arm64 with Apple clang 21, it segfaulted in 4 out of 4 runs
without this change, and passed 5 out of 5 runs with it.

[Bug #22476]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 11:42:34 +01:00
..