Skip to content

Conversation

cfallin
Copy link
Member

@cfallin cfallin commented Sep 12, 2025

In #11682 we see a module with an extremely large single function body (function index 193). This causes a panic in Cranelift as we run out of SSA value numbers: the ValueDataPacked bit-packing supports only 2^24 (16M) values per function.

I started down the path of propagating CodegenErrors everywhere throughout Cranelift to properly bubble up a
CodegenError::CodeTooLarge, but that turns out to be an extremely pervasive change: it means not only that we have more Result plumbing, but that (i) Cranelift's public API changes so that all function builder methods return Results, which is a huge change for any existing user; and (ii) ISLE can't generate Rust that propagates Results, so we need to awkwardly set an error flag on a context, return a fake Value, and "catch" it on the other side of the invocation, which is error-prone.

I then considered a size-check on function bodies as they enter Cranelift, but at that point, realized that Wasm already provides for implementation limits for this purpose. The JS embedding spec at https://webassembly.github.io/spec/js-api/index.html#limits specifies that a function body can be at most 7_654_321 bytes (7.65MB). We don't have to follow the JS embedding's implementation limits, but there is good reason to expect that producers will try to stay within them, and the reasons that led to those limits in Web engines' compilers equally apply to ours. This PR thus instead enforces the limit directly.

Fixes #11682.

In bytecodealliance#11682 we see a module with an extremely large single function body
(function index 193). This causes a panic in Cranelift as we run out of
SSA value numbers: the `ValueDataPacked` bit-packing supports only 2^24
(16M) values per function.

I started down the path of propagating `CodegenError`s everywhere
throughout Cranelift to properly bubble up a
`CodegenError::CodeTooLarge`, but that turns out to be an extremely
pervasive change: it means not only that we have more Result plumbing,
but that (i) Cranelift's public API changes so that all function builder
methods return Results, which is a huge change for any existing user;
and (ii) ISLE can't generate Rust that propagates Results, so we need to
awkwardly set an error flag on a context, return a fake Value, and
"catch" it on the other side of the invocation, which is error-prone.

I then considered a size-check on function bodies as they enter
Cranelift, but at that point, realized that Wasm already provides for
implementation limits for this purpose. The JS embedding spec at
https://webassembly.github.io/spec/js-api/index.html#limits specifies
that a function body can be at most 7_654_321 bytes (7.65MB). We don't
*have* to follow the JS embedding's implementation limits, but there is
good reason to expect that producers will try to stay within them, and
the reasons that led to those limits in Web engines' compilers equally
apply to ours. This PR thus instead enforces the limit directly.

Fixes bytecodealliance#11682.
@cfallin cfallin requested review from a team as code owners September 12, 2025 00:05
@cfallin cfallin requested review from fitzgen and removed request for a team September 12, 2025 00:05
@fitzgen
Copy link
Member

fitzgen commented Sep 12, 2025

It might be better to enforce this in wasmparser, where we enforce the rest of these implementation limits:

https://github.com/bytecodealliance/wasm-tools/blob/35f8671bce74190ef0b00ce36c399b053b490374/crates/wasmparser/src/limits.rs#L18-L44

@cfallin
Copy link
Member Author

cfallin commented Sep 12, 2025

Good point -- opened bytecodealliance/wasm-tools#2302 for this.

@cfallin cfallin closed this Sep 12, 2025
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.

wasmtime panics when dealing with very large functions when optimizations are enabled.
2 participants