code wiki / (root) / _derefcast_minrepro.nx

_derefcast_minrepro.nx source

↩ module page · 47 lines · 1563 B

1// _derefcast_minrepro.nx -- min repro: deref + pointer-cast in ONE 2// expression (`*p as *u8`) miscompiles on the native x86 lane. 3// 4// Found 2026-06-10 building nx_tls13_ch_compat_test (B2 row): a 5// pointer value stored through an out-param read back via 6// let host: *u8 = *host_p as *u8 7// then dereferenced -> SIGSEGV. Flattening into 8// let hv: i64 = host_p[0] 9// let host: *u8 = hv as *u8 10// compiles correctly. Same family as the 4-deep nested-if and 11// >6-arg tail-call landmines: expression-shape miscompile. 12// 13// exit 0 = BOTH shapes work (defect fixed -- browser-gate row). 14// exit 1/2 = a shape produced a wrong value; SIGSEGV = the original 15// defect (pre-fix compilers byte-load the cell and deref garbage). 16// 17// FIXED 2026-06-10: parse_unary wrapper owns the trailing `as` so 18// prefix `*` binds tighter than `as` (see nx_parse.nx). This row 19// guards the lane against precedence regressions, like _arg7_minrepro 20// guards the >6-arg tail-call drop. 21// 22// expect_exit: 0 23// license_tier: ORIGINAL 24 25import "nx_syscalls.nx" 26 27func main() -> i64 { 28 let buf: *u8 = sys_mmap(64) 29 buf[0] = 42 as u8 30 31 // Stash the pointer in an i64 cell (the out-param pattern). 32 let cell: *i64 = sys_mmap(16) as *i64 33 cell[0] = buf as i64 34 35 // Flattened shape (known-good). 36 let hv: i64 = cell[0] 37 let p1: *u8 = hv as *u8 38 let v1: i64 = p1[0] & 0xff 39 40 // One-expression shape (the suspect). 41 let p2: *u8 = *cell as *u8 42 let v2: i64 = p2[0] & 0xff 43 44 if v1 != 42 { return 1 } 45 if v2 != 42 { return 2 } 46 return 0 47}