Commit 56d1e8e
* fix(runtime): arr[Symbol.iterator] read an array's capacity as a class_id (#7563)
ObjectHeader is { object_type: u32, class_id: u32, ... } and ArrayHeader is
{ length: u32, capacity: u32 }, so the two u32s at offset 4 alias: an array
pointer read as an ObjectHeader reports its capacity as a class_id.
arr[Symbol.iterator] resolves through js_class_method_bind(arr, "values"), and
that builder's receiver->class step, class_id_from_method_receiver, read the
field with a bare (*obj).class_id -- guarded against closures and the handle
band, but never against the allocation's actual type. So whenever the class
whose id equalled the array's capacity owned a method named `values`, the
array's iterator resolved to THAT class's method. When it was the calling
class, `values` re-entered `values` until the stack guard page: EXC_BAD_ACCESS
at `str xzr, [sp], #-0x50`, ~26 000 frames deep.
Reported as a `class X extends Map` values() override bug, but Map is
incidental and so is the iteration -- the crash reproduces with no Map in the
program and no for-of on the path:
class Plain { values() { return [777][Symbol.iterator](); } }
new Plain().values(); // SIGSEGV
Use js_object_get_class_id, the guarded accessor that already existed for this
read: it rejects the handle band, the std::alloc'd Map/Set/Regex headers (no
GcHeader to probe), and any allocation whose GcHeader.obj_type is not
GC_TYPE_OBJECT. The sibling symbol-method arm in native_call_method.rs already
routed through it and was never affected -- verified, not assumed.
Not #7561: rewrite_collection_view_for_of declines a subclass receiver exactly
as documented, and the offending line predates it by hundreds of commits
(traces through #5631's file split to #4630), matching the report that it
reproduces at 969b447.
Coverage: test-files/test_gap_7563_array_iterator_class_id_confusion.ts
(byte-compared against node; SIGSEGVs at the parent commit) and
object::tests::array_receiver_is_never_read_as_a_class_id (fails with Some(16),
the array's capacity, before the fix).
* chore: bump version
---------
Co-authored-by: Ralph Küpper <ralph@skelpo.com>
1 parent b5a2954 commit 56d1e8e
7 files changed
Lines changed: 416 additions & 80 deletions
File tree
- changelog.d
- crates/perry-runtime/src/object
- test-files
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
0 commit comments