vouillon added the bug label to Issue #10181.
vouillon opened issue #10181:
Test Case
Steps to Reproduce
Run the following command:
./target/debug/wasmtime -W=all-proposals=y constprop.wasm
Expected Results
This works fine if one add the
-C collector=null
option:$ ./target/debug/wasmtime -C collector=null -W=all-proposals=y constprop.wasm booleans: passed integers: passed floats: passed 32-bit integers: passed native integers: passed 64-bit integers: passed integer conversions: passed 32-bit integer conversions: passed native integer conversions: passed 64-bit integer conversions: passed
Actual Results
This crashes with an
Illegal instruction
error.Versions and Environment
Wasmtime commit: 0e0560087beff704bc111a1abb1d6a80c1b5da70
Operating system: Linux
Architecture: x64
alexcrichton assigned afonso360 to issue #10181.
alexcrichton assigned fitzgen to issue #10181.
alexcrichton unassigned afonso360 from issue #10181.
fitzgen commented on issue #10181:
Thanks for the bug report!
If you have time, minimizing the test case
wat
withcreduce
would be very appreciated and make diagnosing and fixing this easier. If not, I'll get around to that eventually.
fitzgen added the wasm-proposal:gc label to Issue #10181.
just-an-engineer commented on issue #10181:
I'll take this.
After some initial looking, it has to do with the async stuff, I'm guessing it pops the wrong address somehow.
just-an-engineer commented on issue #10181:
Where is this wasm file from, and how did you compile it?
I suspect it may be from an invalid wasm file, which the code _should_ check for currently, but doesn't seem to. Runningwasm-validate
on it gives me an error of invalid type a few bytes in, but I imagine that tools stops after the first error, so no idea how many more.
Anyways, it could be that there's some invalid stuff here that operates outside of the specification, that leds to an incorrect address being jumped to during the async execution stuffs.
vouillon commented on issue #10181:
This code relies on the Wasm GC proposal. This proposal is not supported by
wasm-validate
. That's why you get errors.
The code is generated using wasm_of_ocaml, which compiles OCaml code to Wam.
The source code comes from the OCaml test suite, so it is a bit weird.
wasm-opt
from the binaryen toolchain is used to optimize the code. And the code runs fine innode
. So I'm quite confident regarding its validity.
fitzgen commented on issue #10181:
@just-an-engineer
I'll take this.
You're definitely welcome to investigate this bug, but this isn't likely the best good-first-issue kind of bug if you aren't already somewhat familiar with Wasmtime and Cranelift.
What would be super helpful whether you continue to investigate this bug or leave it for someone else would be to run
creduce
on the.wat
disassembly of the test case and reduce it to a minimal example that triggers the illegal instruction fault. This would involve something like:
wasm-tools wasm2wat test.wasm -o test.wat
Writing a
predicate.sh
that does something like
sh #!/usr/bin/env bash set -eu cargo run --manifest-path ~/path/to/wasmtime/Cargo.toml -- \ -C collector=null -W=all-proposals=y \ test.wat \ 2>&1 | grep -q 'Illegal instruction'
(Note: the above is untested, you would want to make sure that it exits1
iftest.wasm
doesn't trigger the illegal instruction and0
if it does trigger the illegal instruction.)And finally run
creduce
something like
creduce --not-c predicate.sh test.wat
And when
creduce
is finished, post the reduced test case here.I suspect it may be from an invalid wasm file
Wasmtime always validates the Wasm as part of its process of translating it to Cranelift's IR (called CLIF) so, barring validator bugs, we should never actually execute any invalid Wasm file.
vouillon commented on issue #10181:
I have used
wasm-reduce
(from the Binaryen toolchain) andcreduce
, plus some manual rewriting, to reduce the size of the code. It remains a bit large, probably because one needs a specific allocation pattern to trigger the bug. In particular, there is a global array which is not used anywhere, and some values that are dropped right after being allocated.
A circular datastructure is built usingstruct.set
. Maybe this confuses the GC? I don't see anything else suspicious.
constprop.wat.txt
tanishiking commented on issue #10181:
We encountered an "Illegal Instruction" error in our project (scala-wasm fork of Scala.js to support wasm component model).
I'm not sure if this is the only case, but the error occurs at least when we try to set an
i31
value (converted from i32 with the MSB has 1) to ananyref
struct field.(module (type $c.scala.Tuple1 (sub (struct (field $f.scala.Tuple1._1 (mut anyref))))) (func (export "test") (local $instance (ref $c.scala.Tuple1)) i32.const -2 ref.i31 struct.new $c.scala.Tuple1 drop ) )
$ wasm-tools parse test.wat -o test.wasm $ wasmtime run -W function-references,gc --invoke test test.wasm make: *** [run] Illegal instruction: 4
see: https://github.com/tanishiking/kitchensink/tree/main/wasmtime-illegal-instruction
As @vouillon mentioned, the problem doesn't happen when using the
-C collector=null
option.$ wasmtime --version wasmtime 29.0.1 (58282df89 2025-01-21)
tanishiking edited a comment on issue #10181:
We encountered an "Illegal Instruction" error in our project (scala-wasm fork of Scala.js to support wasm component model).
I'm not sure if this is the only case, but the error occurs at least when we try to set an
i31
value (converted from i32 with the MSB has 1) to ananyref
struct field.(module (type $c.scala.Tuple1 (sub (struct (field $f.scala.Tuple1._1 (mut anyref))))) (func (export "test") (local $instance (ref $c.scala.Tuple1)) i32.const -2 ref.i31 struct.new $c.scala.Tuple1 drop ) )
$ wasm-tools parse test.wat -o test.wasm $ wasmtime run -W function-references,gc --invoke test test.wasm make: *** [run] Illegal instruction: 4
see: https://github.com/tanishiking/kitchensink/tree/main/wasmtime-illegal-instruction
- As @vouillon mentioned, the problem doesn't happen when using the
-C collector=null
option.- I guess there're other reproductions as well, because I find there's only
(ref.i31 (i32.const 0))
in @vouillon 's reproduction case.$ wasmtime --version wasmtime 29.0.1 (58282df89 2025-01-21)
tanishiking edited a comment on issue #10181:
We encountered an "Illegal Instruction" error in our project (scala-wasm fork of Scala.js to support wasm component model).
I'm not sure if this is the only case, but the error occurs at least when we try to set an
i31
value (converted from i32 with the MSB has 1) to ananyref
struct field.(module (type $c.scala.Tuple1 (sub (struct (field $f.scala.Tuple1._1 (mut anyref))))) (func (export "test") (local $instance (ref $c.scala.Tuple1)) i32.const -1 ref.i31 struct.new $c.scala.Tuple1 drop ) )
$ wasm-tools parse test.wat -o test.wasm $ wasmtime run -W function-references,gc --invoke test test.wasm make: *** [run] Illegal instruction: 4
see: https://github.com/tanishiking/kitchensink/tree/main/wasmtime-illegal-instruction
- As @vouillon mentioned, the problem doesn't happen when using the
-C collector=null
option.- I guess there're other reproductions as well, because I find there's only
(ref.i31 (i32.const 0))
in @vouillon 's reproduction case.$ wasmtime --version wasmtime 29.0.1 (58282df89 2025-01-21)
tanishiking edited a comment on issue #10181:
We encountered an "Illegal Instruction" error in our project (scala-wasm fork of Scala.js to support wasm component model).
The error occurs at least when we try to set an
i31
value (converted from i32 with the MSB has 1) to ananyref
struct field.(module (type $c.scala.Tuple1 (sub (struct (field $f.scala.Tuple1._1 (mut anyref))))) (func (export "test") (local $instance (ref $c.scala.Tuple1)) i32.const -1 ref.i31 struct.new $c.scala.Tuple1 drop ) )
$ wasm-tools parse test.wat -o test.wasm $ wasmtime run -W function-references,gc --invoke test test.wasm make: *** [run] Illegal instruction: 4
see: https://github.com/tanishiking/kitchensink/tree/main/wasmtime-illegal-instruction
- As @vouillon mentioned, the problem doesn't happen when using the
-C collector=null
option.- I guess there're other reproductions as well, because I find there's only
(ref.i31 (i32.const 0))
in @vouillon 's reproduction case.$ wasmtime --version wasmtime 29.0.1 (58282df89 2025-01-21)
tanishiking commented on issue #10181:
This particular example https://github.com/bytecodealliance/wasmtime/issues/10181#issuecomment-2665004815 has fixed in local-built wasmtime (287e8fb5405a943f67babf08643e23bea449e7bf) :tada: thanks! maybe https://github.com/bytecodealliance/wasmtime/pull/10091 was the fix?
but we still hit the
Illegal instruction: 4
error in larger binary, I'll share it when I could make a bit smaller reproducible example.
tanishiking edited a comment on issue #10181:
This particular example https://github.com/bytecodealliance/wasmtime/issues/10181#issuecomment-2665004815 has fixed in local-built wasmtime (287e8fb5405a943f67babf08643e23bea449e7bf) :tada: not sure what was the fix though.
but we still hit the
Illegal instruction: 4
error in larger binary, I'll share it when I could make a bit smaller reproducible example.
tanishiking edited a comment on issue #10181:
This particular example https://github.com/bytecodealliance/wasmtime/issues/10181#issuecomment-2665004815 has fixed in local-built wasmtime (287e8fb5405a943f67babf08643e23bea449e7bf) :tada: not sure what was the fix though.
We still hit the
Illegal instruction: 4
error in larger binary, I'll share it when I could make a bit smaller reproducible example.
Last updated: Feb 28 2025 at 02:27 UTC