saulecabrera added the fuzz-bug label to Issue #10418.
saulecabrera added the bug label to Issue #10418.
saulecabrera opened issue #10418:
For the following program:
(module (type (;0;) (func (param i32) (result i64))) (global (;0;) (mut i32) i32.const 0) (global (;1;) (mut i64) i64.const 0) (global (;2;) (mut i32) i32.const 0) (export " " (func 0)) (func (;0;) (type 0) (param i32) (result i64) i32.const 0 if ;; label = @1 unreachable end global.get 2 global.set 2 i64.const 288230376151711744 i64.const 288230376151711744 i64.mul_wide_s i32.wrap_i64 global.get 0 i32.xor global.set 0 global.get 1 i64.xor ) )
When invoked via:
cargo run -- run -Wwide-arithmetic=y --invoke " " index.wat 0
The result, using
-Ccompiler=cranelift
or-Ccompiler=winch
or--target=pulley64
is consistently the same:0
. However, when invoked via:wasm_cli --invoke " " index.wat 0
The result is
4503599627370496
Reducing a bit further, it seems the the problem is the ordering of the return values from
i64.mul_wide_s
Consider:
(module (type (;0;) (func (param i32) (result i64))) (global (;0;) (mut i32) i32.const 0) (global (;1;) (mut i64) i64.const 0) (global (;2;) (mut i32) i32.const 0) (export " " (func 0)) (func (;0;) (type 0) (param i32) (result i64) i32.const 0 if ;; label = @1 unreachable end global.get 2 global.set 2 i64.const 288230376151711744 i64.const 288230376151711744 i64.mul_wide_s drop ) )
The result for Wasmtime (using any of the compilers or pulley) is:
0
.
Usingwasmi
the result is:4503599627370496
Which clearly suggests that there's a discrepancy on how the results of
i64.mul_wide_s
are handled inwasmi
. According to the consistent results in Wasmtime, I'm tempted to suggest that this probably a bug inwasmi
itself, however, I'm opening this issue here first for confirmation.cc @alexcrichton @Robbepop
Robbepop commented on issue #10418:
Since the
wide-arithmetic
support in Wasmi is fairly new it likely is a bug in Wasmi. Going to inspect it as soon as I find time.
saulecabrera edited issue #10418:
For the following program:
(module (type (;0;) (func (param i32) (result i64))) (global (;0;) (mut i32) i32.const 0) (global (;1;) (mut i64) i64.const 0) (global (;2;) (mut i32) i32.const 0) (export " " (func 0)) (func (;0;) (type 0) (param i32) (result i64) i32.const 0 if ;; label = @1 unreachable end global.get 2 global.set 2 i64.const 288230376151711744 i64.const 288230376151711744 i64.mul_wide_s i32.wrap_i64 global.get 0 i32.xor global.set 0 global.get 1 i64.xor ) )
When invoked via:
cargo run -- run -Wwide-arithmetic=y --invoke " " index.wat 0
The result, using
-Ccompiler=cranelift
or-Ccompiler=winch
or--target=pulley64
is consistently the same:0
. However, when invoked via:wasmi_cli --invoke " " index.wat 0
The result is
4503599627370496
Reducing a bit further, it seems the the problem is the ordering of the return values from
i64.mul_wide_s
Consider:
(module (type (;0;) (func (param i32) (result i64))) (global (;0;) (mut i32) i32.const 0) (global (;1;) (mut i64) i64.const 0) (global (;2;) (mut i32) i32.const 0) (export " " (func 0)) (func (;0;) (type 0) (param i32) (result i64) i32.const 0 if ;; label = @1 unreachable end global.get 2 global.set 2 i64.const 288230376151711744 i64.const 288230376151711744 i64.mul_wide_s drop ) )
The result for Wasmtime (using any of the compilers or pulley) is:
0
.
Usingwasmi
the result is:4503599627370496
Which clearly suggests that there's a discrepancy on how the results of
i64.mul_wide_s
are handled inwasmi
. According to the consistent results in Wasmtime, I'm tempted to suggest that this probably a bug inwasmi
itself, however, I'm opening this issue here first for confirmation.cc @alexcrichton @Robbepop
Robbepop edited a comment on issue #10418:
Since the
wide-arithmetic
support in Wasmi is fairly new it likely is a bug in Wasmi. Going to inspect it as soon as I find time.
From my understanding thedrop
instructions drops the high 64-bits of the result.
288230376151711744^2 ~= 8,30767497e34
and8,30767497e34 / 2^64 = 4503599627370496
Robbepop edited a comment on issue #10418:
Since the
wide-arithmetic
support in Wasmi is fairly new it likely is a bug in Wasmi. Going to inspect it as soon as I find time.From my understanding the
drop
instructions drops the high 64-bits of the result.
288230376151711744^2 ~= 8,30767497e34
and8,30767497e34 / 2^64 = 4503599627370496
alexcrichton commented on issue #10418:
@Robbepop this program:
fn main() { let a = 288230376151711744_i64; let b = 288230376151711744_i64; println!("{a} * {b} = {}", a.wrapping_mul(b)); println!("{a:#x} * {b:#x} = {:#x}", a.wrapping_mul(b)); let a = i128::from(a); let b = i128::from(b); println!("{a} * {b} = {}", a.wrapping_mul(b)); println!("{a:#x} * {b:#x} = {:#x}", a.wrapping_mul(b)); }
prints
288230376151711744 * 288230376151711744 = 0 0x400000000000000 * 0x400000000000000 = 0x0 288230376151711744 * 288230376151711744 = 83076749736557242056487941267521536 0x400000000000000 * 0x400000000000000 = 0x100000000000000000000000000000
so I think it's expected that the low bits are all zero?
Robbepop commented on issue #10418:
@alexcrichton indeed, it seems that Wasmi const-eval for
wide-arithmetic
is off here. Sorry about that!
alexcrichton closed issue #10418:
For the following program:
(module (type (;0;) (func (param i32) (result i64))) (global (;0;) (mut i32) i32.const 0) (global (;1;) (mut i64) i64.const 0) (global (;2;) (mut i32) i32.const 0) (export " " (func 0)) (func (;0;) (type 0) (param i32) (result i64) i32.const 0 if ;; label = @1 unreachable end global.get 2 global.set 2 i64.const 288230376151711744 i64.const 288230376151711744 i64.mul_wide_s i32.wrap_i64 global.get 0 i32.xor global.set 0 global.get 1 i64.xor ) )
When invoked via:
cargo run -- run -Wwide-arithmetic=y --invoke " " index.wat 0
The result, using
-Ccompiler=cranelift
or-Ccompiler=winch
or--target=pulley64
is consistently the same:0
. However, when invoked via:wasmi_cli --invoke " " index.wat 0
The result is
4503599627370496
Reducing a bit further, it seems the the problem is the ordering of the return values from
i64.mul_wide_s
Consider:
(module (type (;0;) (func (param i32) (result i64))) (global (;0;) (mut i32) i32.const 0) (global (;1;) (mut i64) i64.const 0) (global (;2;) (mut i32) i32.const 0) (export " " (func 0)) (func (;0;) (type 0) (param i32) (result i64) i32.const 0 if ;; label = @1 unreachable end global.get 2 global.set 2 i64.const 288230376151711744 i64.const 288230376151711744 i64.mul_wide_s drop ) )
The result for Wasmtime (using any of the compilers or pulley) is:
0
.
Usingwasmi
the result is:4503599627370496
Which clearly suggests that there's a discrepancy on how the results of
i64.mul_wide_s
are handled inwasmi
. According to the consistent results in Wasmtime, I'm tempted to suggest that this probably a bug inwasmi
itself, however, I'm opening this issue here first for confirmation.cc @alexcrichton @Robbepop
Robbepop commented on issue #10418:
@saulecabrera @alexcrichton The bug has been fixed in Wasmi yesterday and today I released Wasmi v0.42.1 that includes this fix. So technically Wasmtime fuzzing could use v0.42.1 again with
wide-arithmetic
enabled if you feel like it makes sense. Not sure so I didn't create a PR, yet.
Robbepop edited a comment on issue #10418:
@saulecabrera @alexcrichton The bug has been fixed in Wasmi yesterday and today I released Wasmi v0.42.1 that includes this fix. So technically Wasmtime fuzzing could use v0.42.1 again with
wide-arithmetic
enabled if you feel like it makes sense. Not sure so I didn't create a PR, yet.The fix was trivial: https://github.com/wasmi-labs/wasmi/pull/1397
alexcrichton commented on issue #10418:
Thanks! Opened up https://github.com/bytecodealliance/wasmtime/pull/10430 to re-enable
Last updated: Apr 17 2025 at 10:03 UTC