Skip to content

[Potential Bug]: vN.storeN_lane writes to the wrong address (x86-64 interpreter) #649

Description

@khagankhan

Engine: Wizard 26.2985 · Tiers affected: int, dyn (x86-64 assembly interpreter). lazy/jit/spc are correct.

Symptom

v128.store{8,16,32,64}_lane stores the correct lane value to the wrong address:
it writes to mem_base + lane_immediate instead of the computed effective address.
No trap, silently wrong memory.

Minimal reproducer

(module
  (memory (export "_memory") 1)
  (func (export "main") (result i32)
    i32.const 256
    v128.const i32x4 0x0036fda8 0x0076015d 0xfccb0211 0xfdb5fd1a
    v128.store8_lane offset=0 6     ;; should write byte 0x76 to addr 256
    i32.const 256
    i32.load8_u))                   ;; reads back addr 256
int/dyn -> 0     (0x76 was written to addr 6 = the lane immediate)
spc/jit/lazy/wasmi -> 118 (0x76)   ;; correct

Root cause

genStoreLane in src/engine/x86-64/X86_64Interpreter.v3 reuses r_tmp0 for two
things
: decode_memarg builds the effective address in r_tmp0, then
load_imm8(idx) overwrites r_tmp0 with the lane immediate before the store runs,
so the store targets [mem_base + lane]. (genLoadLane is correct because it uses a
separate register for the address.)

Fix

In genStoreLane, keep the address in r_tmp0 and put the lane immediate in the
spare r_tmp2. (r_tmp0 must stay the memarg dest — genReadUleb32 rejects
r_scratch == r_tmp2.)

-		def idx: X86_64Gpr = r_tmp0;
-		def val: X86_64Gpr = r_tmp1;
-		def mem_addr = decode_memarg(vsph[-2].value, idx, val);
-		load_imm8(idx);
+		def addr: X86_64Gpr = r_tmp0; // effective store address (must survive)
+		def val: X86_64Gpr = r_tmp1;
+		def lane: X86_64Gpr = r_tmp2; // lane immediate in its own register
+		def mem_addr = decode_memarg(vsph[-2].value, addr, val);
+		load_imm8(lane);
 		asm.q.lea(val, data);
-		asm_mov_r_m(val, X86_64Addr.new(val, idx, size, 0));
+		asm_mov_r_m(val, X86_64Addr.new(val, lane, size, 0));
 		asm_mov_m_r(mem_addr, val);

Verified: all store{8,16,32,64}_lane widths/lanes agree int==spc after the fix,
and the original fuzz seed now agrees across all 5 tiers + wasmi.

Additional information

A combination of AFL++ and Wasmlike, an Xsmith-based random program generator produced the snippet of code that found the issue. Xsmith Project

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions