Skip to content

SIGSEGV: Array.from() over a Proxy wrapping an array (spread and for…of work) #10270

Description

@proggeramlug

Summary

Array.from(p) where p is a Proxy wrapping an array segfaults (SIGSEGV, exit 139). Spreading and for…of over the same proxy work, so the value is iterable; only Array.from crashes. Found while chasing OpenCode's request path (tracker #10107).

Repro

const t = (name: string, f: () => any) => { try { console.log(name, JSON.stringify(f())) } catch (e: any) { console.log(name, "THROW", e.message) } }
const pa = () => new Proxy([["x-a", "1"]], {})
t("Q1 [...proxyOverArray]", () => [...(pa() as any)].length)
t("Q2 for..of proxyOverArray", () => { let n = 0; for (const _ of pa() as any) n++; return n })
t("Q3 Array.isArray(proxyOverArray)", () => Array.isArray(pa()))
t("Q4 proxy[Symbol.iterator] typeof", () => typeof (pa() as any)[Symbol.iterator])
t("Q5 Array.from(proxyOverArray)", () => Array.from(pa() as any).length)

perry 0.5.1569 (Linux x86_64), perry compile proxy-iter.ts:

Q1 [...proxyOverArray] 1
Q2 for..of proxyOverArray 1
Q3 Array.isArray(proxyOverArray) true
Q4 proxy[Symbol.iterator] typeof "function"
Segmentation fault (core dumped)      ← Q5

bun 1.3.14 prints Q5 Array.from(proxyOverArray) 1 and continues.

Notes

  • Array.isArray returns true for the proxy, so any code path that branches on it and then takes an array-specific fast path will dereference the proxy id as if it were an ArrayHeader. That is the likely shape of the crash; js_for_of_to_array on such a value is reachable from the Headers constructor too (new Headers(new Proxy([["a","1"]], {}))), which is how I found it.
  • A crash rather than a TypeError makes this worse than a plain correctness gap: it takes the whole process down with no JS-level stack.

Related: the Headers record-init proxy gap I am fixing separately, and tracker #10107.

Activity

  1. proggeramlug commented on Sep 15, 2026

    @proggeramlug
    ContributorAuthor

    Ready-for-review fix: #10280

    The exact compiled reproduction now reaches Q5 and matches bun. The new regression test exits 139 on pristine 1cd160f3d and passes with the fix. The PR documents the raw GC-header probe in the unmapped clone path, the IsArray-trusting mapped path, sibling fixes/audit, and before/after benchmarks (+0.20% for plain-array Array.from, within measured variation). It also fixes #10274 and references #10107. The unrelated runtime-suite failure reproduced on main is documented in validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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