Skip to content

abort on allocation failure in wasip1 cabi_realloc - #1315

Merged
saulecabrera merged 1 commit into
bytecodealliance:mainfrom
nabeel-dev21:cabi-realloc-alloc-failure
Oct 18, 2026
Merged

saulecabrera merged 1 commit into
bytecodealliance:mainfrom
nabeel-dev21:cabi-realloc-alloc-failure

Conversation

@nabeel-dev21

Copy link
Copy Markdown
Contributor

Description of the change

cabi_realloc in the wasip1 plugin ABI uses the result of alloc::alloc without checking it for null. Address 0 is ordinary linear memory on Wasm, so when the allocation fails the host gets 0 back as a success value. The CLI's compile step and every module javy build emits then memory.write / memory.init the JS source, bytecode or export name at address 0 (the far end of the shadow stack in the default plugin, which starts at 1 MiB), and the realloc branch would copy_nonoverlapping the old contents through the null pointer. Reproduced against the current plugin with wasmtime's memory cap:

$ wasmtime run -W max-memory-size=16777216 --invoke cabi_realloc plugin.wasm 0 0 1 67108864
0

The same thing shows up end to end. A javy build module with 704 KB of bytecode, run with a cap 512 KB above its initial memory, keeps executing with the bytecode copied over the start of memory and dies later inside QuickJS with an unrelated [uninitialized] or out of memory error. With this change the run stops at the copy with memory allocation of 703944 bytes failed.

The allocation now goes through alloc::handle_alloc_error, so the failure prints and aborts (an unreachable trap). That is what wit-bindgen's cabi_realloc does for the wasip2 plugins and what any other failed allocation in the plugin already does. The new CLI integration test instantiates the plugin under a 16 MiB StoreLimits cap and checks that an oversized cabi_realloc traps with the allocation failure on stderr; it fails on the current plugin, which returns 0.

Why am I making this change?

Hosts that run Javy output commonly cap instance memory, and a cap hit while the bytecode or source is being copied in currently turns into a silent write over the start of linear memory rather than a reportable error. Checking inside cabi_realloc keeps the ABI's contract (a returned pointer is valid for new_size bytes) local to the one function that promises it.

Checklist

  • I've updated the default plugin import namespace and incremented the major version of javy-plugin-api if the QuickJS bytecode has changed.
  • I've updated the relevant CHANGELOG files if necessary. Changes to javy-cli, javy-plugin, and javy-plugin-processing do not require updating CHANGELOG files.
  • I've updated the relevant crate versions if necessary. Versioning policy for library crates
  • I've updated documentation including crate documentation if necessary.

@saulecabrera
saulecabrera merged commit b49fa3b into bytecodealliance:main Oct 18, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants