WasmKernelFixtures

The shared malicious- and well-behaved-kernel vectors for WasmRuntimeConformanceSuite.

One canonical byte set for every target: Kotlin/Native and wasmJs have no classpath resources, so the fixtures are embedded as byte literals and shared from commonMain — every WasmRuntime implementation is verified against identical bytes. Each vector's .wat source lives in this module's wat/ directory with a wat2wasm reproduction command in its header.

All loadable vectors declare linear memory with an explicit bounded max (the uniform contract — see us.tractat.kuilt.warp.WasmRuntime); the deliberate exceptions are the guard vectors themselves (NO_MAX_MEMORY, OVERSIZE_INITIAL_MEMORY, MISSING_MEMORY), plus INITIAL_ABOVE_DECLARED_MAX, which declares a bounded max the WebAssembly spec would refuse to validate against its own initial — see its KDoc for why that is the only way to reach the guard it targets.

The vectors that carry a descriptor rather than bare bytes — OOB_IN_RANGE_RESULT, GROW_THEN_WRITE, INITIAL_ABOVE_DECLARED_MAX and INITIAL_AT_CAP — are by lazy rather than eager, and that is a diagnostic decision, not a performance one. Their descriptors validate themselves on construction, and an eager val runs that validation in this object's initializer: measured, a fixture drifted back into the high-bit region reddened 19 of 20 conformance tests as ExceptionInInitializerError / NoClassDefFoundError, with the sentence naming the violated relation buried in exactly one of them. Lazily, the same drift reds only the properties that use the vector, and reds them with the message.

Properties

Link copied to clipboard

loop.wat (87 bytes) — the CPU bomb: warp_run spins forever on a backward branch (loop/br) with NO function call in the loop body, so only the execution-time bound can stop it. Memory declared 1 16 so every load-time guard passes.

Link copied to clipboard

growmax.wat (93 bytes) — memory declared 1 1; warp_run executes memory.grow(1) (which would need 2 pages) and converts the engine's grow denial (-1) into unreachable. Proves the engine enforces a module's DECLARED max at grow time — the evidence that reject-no-max is a sufficient memory ceiling.

Link copied to clipboard

growwrite.wat (136 bytes) — memory declared 1 2; warp_run grows it by one page mid-call, writes its result entirely inside the page that did not exist a moment ago, and returns a pointer into it.

Link copied to clipboard

ooballoc.wat (86 bytes) — warp_alloc returns 0x8000_0000: an alloc pointer with bit 31 set. Signed-int narrowing would wrap it negative and WRITE the marshalled args below the linear-memory base — a sandbox-escape OOB host-memory write.

Link copied to clipboard

badreslen.wat (86 bytes) — warp_run returns packed (resPtr = 0, resLen = 0x8000_0000): a result length with bit 31 set. Signed-int narrowing would wrap it negative and hit a raw negative-size allocation escaping the sealed exception hierarchy.

Link copied to clipboard

oobresptr.wat (91 bytes) — warp_run returns packed (resPtr = 0x8000_0000, resLen = 4): a result pointer with bit 31 set. Signed-int narrowing would wrap it negative and read host memory below the linear-memory base — a sandbox-escape OOB read.

Link copied to clipboard

imports.wat (100 bytes) — the capability-violation vector: declares one imported host function (env.host). Memory is bounded (1 1) so the import is the ONLY violation and the rejection message must name the capability violation.

Link copied to clipboard

initovermax.wat (82 bytes) — declares memory 32 16: an initial of 32 pages above the default 16-page cap, with an explicit max sitting exactly at the cap.

Link copied to clipboard

capinit.wat (82 bytes) — declares memory 16 16: an initial and a max sitting exactly on the default 16-page cap. Wholly legal, so it must load and run.

Link copied to clipboard

noabi.wat (26 bytes) — well-formed (no imports, bounded memory 1 1) but omits the warp_alloc/warp_run ABI exports. Must be a TERMINAL load rejection, never a raw engine error that escapes the sealed exception hierarchy.

Link copied to clipboard

nomemory.wat (67 bytes) — exports the ABI functions but declares no linear memory; the warp ABI needs memory to marshal args/results, so load must reject it.

Link copied to clipboard

nomax.wat (144 bytes) — the memory-bomb vector: the REVERSE kernel with memory declared 1 (min 1 page, NO explicit max). A complete warp-ABI module, so the no-max guard is the only thing that can reject it — disabling that guard on any target would let it load and memory.grow unbounded (~4 GiB).

Link copied to clipboard

oobinrange.wat (88 bytes) — the vector the three high-bit siblings above cannot express: warp_run returns (resPtr = 65530, resLen = 100) on a one-page memory. Neither word has bit 31 set, the pointer is an ordinary offset inside linear memory, and the window [65530, 65630) runs 94 bytes past the end of it.

Link copied to clipboard

largeinit.wat (81 bytes) — declares memory 32: an INITIAL size of 32 pages exceeding the default 16-page sandbox cap, and no explicit max.

Link copied to clipboard

bigmem.wat (82 bytes) — declares memory 1 64: an explicit max of 64 pages, exceeding the default 16-page sandbox cap (us.tractat.kuilt.warp.WasmSandboxConfig.maxMemoryPages).

Link copied to clipboard

reverse.wat (145 bytes) — the well-behaved kernel: exports the full warp ABI and reverses its input bytes. Memory declared 1 16 (explicit max = the default sandbox cap), so every load-time guard passes; the guards must not over-reject it.

Link copied to clipboard

startbomb.wat (97 bytes) — the load-phase CPU bomb: a (start) function spinning forever on a backward branch (loop/br), run at instantiation — before any ABI call — so only a load-phase execution bound can stop it. Otherwise a complete well-behaved warp kernel (memory 1 16, both ABI exports), so every load-time guard passes.

Link copied to clipboard

trap.wat (81 bytes) — warp_run immediately executes unreachable, trapping at runtime. Memory declared 1 1 so it loads past every guard.