A .cts whose strict arm contains a frozen class instance with a field named
caller, written with +=, segfaults — and the fault lands on an earlier
statement in the same function, so it is a module-shape effect rather than a bad
statement.
* thread #1, stop reason = EXC_BAD_ACCESS (code=1, address=0x23c88c00000)
frame #0: perry_runtime::object::field_set_by_name::tail::set_field_by_name_object_tail + 812
-> ldrb w11, [x9], #0x1 ; key_bytes_hash reading the key
eor x11, x1, x11
mul x1, x11, x10
set_field_by_name_object_tail is hashing a garbage key pointer: the
receiver/key reached the by-name setter with the key naming unmapped memory.
Repro
Attached repro (also reproducible from
test-files/test_gap_9459_property_set_strictness.cts with a frozen
class CallerCell { caller: number } instance added to its strict arm). Output
stops after
strict frozen for-of head computed: TypeError 1
so the crashing statement is the NEXT one — computedPlus[computedKey] += 1, a
strict compound assignment through the Expr::IndexSet runtime-string-key arm —
even though the trigger is the caller-named class field later in the
function. Removing only the class-field case makes the whole file pass; removing
any other case does not.
What is known
Where to start
The key operand for the strict o[k] += v lane is rooted by
with_operands_rooted_across(ctx, &[object, index], &[value], …) in
expr/index_set.rs, so this is more likely a stale interned-key handle or a
dispatch-id/string-pool index collision than a missing root — the #7201/#7640
family, but the guard is present, so the pointer is probably wrong rather than
merely moved. Dumping --trace llvm for the crashing function and comparing the
key global against the string pool is the first step.
Found while adding caller/arguments receiver-path coverage to
test_gap_9459_property_set_strictness.cts (PR #9519). That fixture omits the
frozen-class-field-named-caller case with a comment pointing here; it belongs
back in the file once this is fixed.
A
.ctswhose strict arm contains a frozen class instance with a field namedcaller, written with+=, segfaults — and the fault lands on an earlierstatement in the same function, so it is a module-shape effect rather than a bad
statement.
set_field_by_name_object_tailis hashing a garbage key pointer: thereceiver/key reached the by-name setter with the key naming unmapped memory.
Repro
Attached repro (also reproducible from
test-files/test_gap_9459_property_set_strictness.ctswith a frozenclass CallerCell { caller: number }instance added to its strict arm). Outputstops after
so the crashing statement is the NEXT one —
computedPlus[computedKey] += 1, astrict compound assignment through the
Expr::IndexSetruntime-string-key arm —even though the trigger is the
caller-named class field later in thefunction. Removing only the class-field case makes the whole file pass; removing
any other case does not.
What is known
main+ the fixture content, and on the Sloppyo.x += 1on a frozen object over-throws: Expr::PropertySet carries no strictness field at all #9459 branch with and without thatPR's only behavioural change to this file. Nothing in Sloppy
o.x += 1on a frozen object over-throws: Expr::PropertySet carries no strictness field at all #9459/SIGSEGV after several frozen for-of-head rejections, then a for-of head on an UNfrozen object #9460 is on thepath — the crashing store is the STRICT lane, which both changes leave
byte-identical.
containing the same three statements and the same class; it needs the full
module. That points at a string-pool / dispatch-id or outlining threshold
rather than at the statement.
calleris load-bearing for the trigger, which issuggestive given the poison-pill special-casing that keys on that name in
field_set_by_name.rsandfield_set_by_name/write_helpers.rs.Where to start
The key operand for the strict
o[k] += vlane is rooted bywith_operands_rooted_across(ctx, &[object, index], &[value], …)inexpr/index_set.rs, so this is more likely a stale interned-key handle or adispatch-id/string-pool index collision than a missing root — the #7201/#7640
family, but the guard is present, so the pointer is probably wrong rather than
merely moved. Dumping
--trace llvmfor the crashing function and comparing thekey global against the string pool is the first step.
Found while adding
caller/argumentsreceiver-path coverage totest_gap_9459_property_set_strictness.cts(PR #9519). That fixture omits thefrozen-class-field-named-
callercase with a comment pointing here; it belongsback in the file once this is fixed.