// Runtime contract for a whole 24B slice header // produced by an UNWRAP source (`mk_sl()!` N_TRYUNW). #6 (Mechanism B, the // deep root, BOTH stages, byte-id-BLIND): the unwrap success-shuffle // materialised {ptr,len,cap}→{AX,BX,CX} ONLY when the success variant was // str; a SLICE success got just `MOVQ DX,AX` (.ptr) — len stayed in CX, cap // in R8, BX junk. So EVERY slice-unwrap consumer (let-receive store, // call-arg push, ident-source) read the wrong .len/.cap. Fix-S widened the // shuffle gate from is_str to type_isstr||type_isslice in both stages // (cgen.c N_TRYPROP/N_TRYUNW + cgenexpr.ww cgtryprop/cgtryunw); str & slice // share the IDENTICAL 24B {ptr,len,cap} ABI shuffle. // // WHY len!=cap and the poison decoys: the original #6 filing was MASKED by // (1) len==cap and (2) a call-source where BX coincidentally held len. Here // mk_sl returns g[0:2] over a backing of cap 5 → len 2, cap 5 (the cap is // the universal tell — it reads CX=len pre-fix). The identsrc decoy seeds // the consumer registers with a distinct sentinel so a dropped word reads // the sentinel, not a coincidence. byte-id is BLIND to this bug (both // stages were identically wrong) — the value asserts are the SOLE tooth. package unwrap_callarg_slice_test; type e = !i32; let g: [5]i32 = [10i32, 20i32, 30i32, 40i32, 50i32]; fn mk_sl() ([]i32 | e) = { return g[0:2]; }; fn slclen(s: []i32) i32 = { return s.len: i32; }; fn slccap(s: []i32) i32 = { return s.cap: i32; }; fn slcsum(s: []i32) i32 = { return s[0] + s[1]; }; @test fn slice_unwrap_letrecv() void = { // let-receive store: MOVQ AX,slot+0 / BX,slot+8 / CX,slot+16. Pre-fix // .cap reads CX (=len 2) — the load-bearing both-stage tell. let s: []i32 = mk_sl()!; assert(s.len: i32 == 2); assert(s.cap: i32 == 5); assert(s[0] + s[1] == 30); }; @test fn slice_unwrap_callarg() void = { // call-arg push of {CX,BX,AX}→{DI,SI,DX}. Decoy ([1i32], cap 1) // poisons the callee's len/cap registers first. let decoy: []i32 = [1i32]; assert(slclen(decoy) == 1); assert(slclen(mk_sl()!) == 2); assert(slccap(mk_sl()!) == 5); assert(slcsum(mk_sl()!) == 30); }; @test fn slice_unwrap_identsrc() void = { // ident source: cgtryunwcursor loads AX/DX/CX/R8 from the frame slot, // never BX → BX = decoy junk, so a .len drop has no coincidence to // hide behind. let r: ([]i32 | e) = mk_sl(); let decoy: []i32 = [99i32, 98i32, 97i32]; assert(slclen(decoy) == 3); assert(slclen(r!) == 2); };