Discovery
PR #100's i64_lowering_doesnt_clobber_params fuzz harness, running on a branch with PR #111's I32WrapI64 fix already applied, finds another AAPCS clobber pattern:
AAPCS clobber: ARM instr at wasm line 3 writes param reg R0 before LocalGet(0) at line 5.
Op: Movw { rd: R0, imm16: 0 }
Sequence:
Push { regs: [R4..R8, LR] }
I64Const { rdlo: R4, rdhi: R5, value: 0 }
I64Extend32S { rdlo: R6, rdhi: R7, rnlo: R4 }
I64Extend32S { rdlo: R8, rdhi: R12, rnlo: R6 }
Movw { rd: R0, imm16: 0 } ← bug: pre-assigns R0
Mov { rd: R0, op2: Reg(R8) } ← function-return placement
Pop { regs: [R4..R8, PC] }
Hypothesis
Likely an i32.const 0 (or similar small const) at wasm line 3 emits Movw rd: R0 because the destination allocator returned R0 — same family as #103/#104/#108/#111 but for a different lowering path. The chain of I64Extend32S means r0 is the next 'free' temp candidate from alloc_temp_safe's round-robin and the live-set tracking doesn't include the still-unread param R0.
Bug class
Same family — hardcoded or naively-allocated R0..R3 in instruction emission.
What to fix
Find the wasm op at line 3 of the fuzz-generated program. Likely I32Const lowering or I64Extend32S post-pass. Audit alloc_temp_safe's exclusion list to make sure live AAPCS params (R0..R(num_params-1)) are always excluded for the entire prefix of the function before each param's first LocalGet.
Status
- The fuzz harness is marked
continue-on-error in CI as of v0.3.0 — finds bugs at a rate faster than we close in one cycle. Promote back to gating once the bug list stabilises.
- Tracking as v0.3.x patch work.
bug aapcs fuzz-found
Discovery
PR #100's
i64_lowering_doesnt_clobber_paramsfuzz harness, running on a branch with PR #111's I32WrapI64 fix already applied, finds another AAPCS clobber pattern:Hypothesis
Likely an
i32.const 0(or similar small const) at wasm line 3 emitsMovw rd: R0because the destination allocator returned R0 — same family as #103/#104/#108/#111 but for a different lowering path. The chain of I64Extend32S means r0 is the next 'free' temp candidate fromalloc_temp_safe's round-robin and the live-set tracking doesn't include the still-unread param R0.Bug class
Same family — hardcoded or naively-allocated R0..R3 in instruction emission.
What to fix
Find the wasm op at line 3 of the fuzz-generated program. Likely
I32Constlowering orI64Extend32Spost-pass. Auditalloc_temp_safe's exclusion list to make sure live AAPCS params (R0..R(num_params-1)) are always excluded for the entire prefix of the function before each param's first LocalGet.Status
continue-on-errorin CI as of v0.3.0 — finds bugs at a rate faster than we close in one cycle. Promote back to gating once the bug list stabilises.bugaapcsfuzz-found