diff --git a/internal/integration_test/fuzz/wazerolib/nodiff.go b/internal/integration_test/fuzz/wazerolib/nodiff.go index 813dc7f2..beb3de83 100644 --- a/internal/integration_test/fuzz/wazerolib/nodiff.go +++ b/internal/integration_test/fuzz/wazerolib/nodiff.go @@ -124,6 +124,38 @@ func requireNoDiff(wasmBin []byte, checkMemory bool, requireNoError func(err err compilerMem.Buffer, interpreterMem.Buffer)) } } + ensureMutableGlobalsMatch(compilerMod, interpreterMod, requireNoError) + } +} + +func ensureMutableGlobalsMatch(compilerMod, interpreterMod api.Module, requireNoError func(err error)) { + ci, ii := compilerMod.(*wasm.ModuleInstance), interpreterMod.(*wasm.ModuleInstance) + for i := range ci.Globals { + cg := ci.Globals[i] + ig := ii.Globals[i] + if !cg.Type.Mutable { + continue + } + + var ok bool + switch ig.Type.ValType { + case wasm.ValueTypeI32, wasm.ValueTypeF32: + ok = uint32(cg.Val) == uint32(ig.Val) + case wasm.ValueTypeI64, wasm.ValueTypeF64: + ok = cg.Val == ig.Val + case wasm.ValueTypeV128: + ok = cg.Val == ig.Val && cg.ValHi == ig.ValHi + default: + ok = true // Ignore other types. + } + + if !ok { + if ig.Type.ValType == wasm.ValueTypeV128 { + requireNoError(fmt.Errorf("mutable global[%d] value mismatch: (%v,%v) != (%v,%v)", i, cg.Val, cg.ValHi, ig.Val, ig.ValHi)) + } else { + requireNoError(fmt.Errorf("mutable global[%d] value mismatch: %v != %v", i, cg.Val, ig.Val)) + } + } } } diff --git a/internal/integration_test/fuzz/wazerolib/nodiff_test.go b/internal/integration_test/fuzz/wazerolib/nodiff_test.go index ed63af98..78f8ec82 100644 --- a/internal/integration_test/fuzz/wazerolib/nodiff_test.go +++ b/internal/integration_test/fuzz/wazerolib/nodiff_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/tetratelabs/wazero/internal/testing/require" + "github.com/tetratelabs/wazero/internal/wasm" ) // TestReRunFailedRequireNoDiffCase re-runs the failed case specified by WASM_BINARY_NAME in testdata directory. @@ -18,3 +19,191 @@ func TestReRunFailedRequireNoDiffCase(t *testing.T) { requireNoDiff(wasmBin, true, func(err error) { require.NoError(t, err) }) } + +func Test_ensureMutableGlobalsMatch(t *testing.T) { + for _, tc := range []struct { + name string + cm, im *wasm.ModuleInstance + expErr string + }{ + { + name: "no globals", + cm: &wasm.ModuleInstance{}, + im: &wasm.ModuleInstance{}, + }, + { + name: "i32 match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}}, + }, + }, + }, + { + name: "i32 match not match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 11, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}}, + }, + }, + expErr: "mutable global[1] value mismatch: 10 != 11", + }, + { + name: "i64 match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}}, + }, + }, + }, + { + name: "i64 match not match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 63, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}}, + }, + }, + expErr: "mutable global[2] value mismatch: 4611686018427387904 != 9223372036854775808", + }, + { + name: "f32 match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}}, + }, + }, + }, + { + name: "f32 match not match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 11, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}}, + }, + }, + expErr: "mutable global[1] value mismatch: 10 != 11", + }, + { + name: "f64 match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}}, + }, + }, + }, + { + name: "f64 match not match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 63, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}}, + }, + }, + expErr: "mutable global[2] value mismatch: 4611686018427387904 != 9223372036854775808", + }, + + { + name: "v128 match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {ValHi: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {ValHi: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}}, + }, + }, + }, + { + name: "v128 match not match", + cm: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}}, + }, + }, + im: &wasm.ModuleInstance{ + Globals: []*wasm.GlobalInstance{ + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}}, + {Val: 1 << 62, ValHi: 1234, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}}, + }, + }, + expErr: "mutable global[2] value mismatch: (4611686018427387904,0) != (4611686018427387904,1234)", + }, + } { + t.Run(tc.name, func(t *testing.T) { + var actualErr error + ensureMutableGlobalsMatch(tc.cm, tc.im, func(err error) { + actualErr = err + }) + if tc.expErr == "" { + require.NoError(t, actualErr) + } else { + require.Equal(t, tc.expErr, actualErr.Error()) + } + }) + } +}