Stream: git-wasmtime

Topic: wasmtime / issue #14946 aarch64: nested `stack_limit` glo...


view this post on Zulip Wasmtime GitHub notifications bot (Oct 22 2026 at 18:00):

alexcrichton added the bug label to Issue #14946.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 22 2026 at 18:00):

alexcrichton added the cranelift label to Issue #14946.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 22 2026 at 18:00):

alexcrichton opened issue #14946:

This test:

test run
target x86_64
target aarch64

;; `%main` passes a fake vmctx where the stack limit chain resolves to 0.
function %callee(i64 vmctx) -> i8 system_v {
    gv0 = vmctx
    gv1 = load.i64 notrap aligned gv0-512
    gv2 = load.i64 notrap aligned gv1-520
    stack_limit = gv2
    ss0 = explicit_slot 64
block0(v0: i64):
    v1 = iconst.i8 1
    return v1
}

function %main() -> i8 system_v {
    ss0 = explicit_slot 2048
    sig0 = (i64 vmctx) -> i8 system_v
    fn0 = %callee sig0
block0:
    v0 = stack_addr.i64 ss0+1024
    v1 = stack_addr.i64 ss0+512
    store.i64 notrap aligned v0, v1
    v2 = stack_addr.i64 ss0+504
    v3 = iconst.i64 0
    store.i64 notrap aligned v3, v2
    v4 = call fn0(v0)
    return v4
}
; run: %main() == 1

fails with:

$ cargo run --target aarch64-unknown-linux-gnu -p cranelift-tools -- test stack-limit-chain.clif
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

It passes on x86_64. The aarch64 prologue for %callee is:

$ cargo run -p cranelift-tools -- compile --target aarch64 -D stack-limit-chain.clif
Disassembly of 60 bytes <%callee>:
   0:   fd 7b bf a9             stp x29, x30, [sp, #-0x10]!
   4:   fd 03 00 91             mov x29, sp
   8:   f0 3f 80 92             mov x16, #-0x200
   c:   10 e8 70 f8             ldr x16, [x0, x16, sxtx]
  10:   f0 40 80 92             mov x16, #-0x208 ; <- clobbers x16, also an address
  14:   10 ea 70 f8             ldr x16, [x16, x16, sxtx]
  18:   10 02 01 91             add x16, x16, #0x40
  1c:   ff 63 30 eb             cmp sp, x16
  20:   c3 00 00 54             b.lo    #0x38
  ...

<details>
<summary>LLM details, if useful</summary>

generate_gv in cranelift/codegen/src/machinst/abi.rs loads every level
of a stack_limit chain into get_stacklimit_reg(), which is x16 on
aarch64, so from the second level on the load is ldr x16, [x16 + off].
When off fits neither SImm9 nor a scaled UImm12, mem_finalize
materialises it into x16 too, overwriting the base before the load (mov x16, #-0x208 above), so the load reads 2*off. The result is a crash or
a garbage stack limit (a missed or spurious stack-overflow trap).

Wasmtime's own chain uses small aligned offsets (ldur x16, [x2, #8]; ldur x16, [x16, #24]), so this isn't reachable from Wasm. A possible fix is to
use x17 for the materialised offset in aarch64's gen_load_base_offset
when base is x16, like LoadAddr does. riscv64 and s390x haven't been
checked for the same pattern.

</details>

view this post on Zulip Wasmtime GitHub notifications bot (Oct 22 2026 at 18:00):

alexcrichton added the cranelift:area:aarch64 label to Issue #14946.


Last updated: Oct 31 2026 at 23:03 UTC