Skip to content

for…of over a Set iterator with a patched .next() segfaults (pre-existing, not #9017) #9019

Description

@proggeramlug

Assigning a patched .next() onto a builtin Set iterator and then driving it with for…of segfaults (exit 139).

Reproducer

const s = new Set<number>([10, 20, 30, 40]);
const it: any = s.values();
let calls = 0;
const orig = it.next.bind(it);
it.next = function () { calls++; return orig(); };
const got: number[] = [];
for (const v of it) got.push(v as number);
console.log("E", calls > 0, got.join(","));

Node 26.5.1 (the pinned oracle) prints E true 10,20,30,40. Perry dies with SIGSEGV before printing anything.

Not a regression — pre-existing

Found while auditing #9017, so I A/B'd it before attributing it. Both arms are --profile perry-dev builds of -p perry -p perry-runtime-static -p perry-stdlib-static, compiled with PERRY_NO_AUTO_OPTIMIZE=1:

build result
#9017 branch exit 139
main @ 06151e61f3 (no #9017) exit 139

So main has it too and #9017 neither causes nor worsens it. Recording that explicitly because the crash surfaces on the exact path #9017 documents ("a patched next wins exactly as it does on the manual path"), which makes it easy to misattribute.

Why it matters beyond the crash

It means the override path on builtin collection iterators has no working end-to-end coverage: any test that would exercise it dies first. #9017 keeps an override probe inside the dispatcher and states that a patched next still wins — that claim cannot currently be validated through for…of, because the baseline crashes.

Scope

  • s.values() with a patched next, driven by for…of → SIGSEGV.
  • The same iterator driven by manual .next() calls is fine (case B/C of my probe: manual .next() returns fresh, correct results).
  • Not yet checked: Map iterators, array iterators, generators, and whether an own next assigned before first use behaves differently. Worth doing when someone picks this up.

No stderr, no panic message — a bare SIGSEGV, so the first step is a debug/ASAN build or PERRY_GC_PROTECT_FROMSPACE=1 to see whether it is a rooting fault or a bad dispatch target.

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