From 00e684e95c44002d863beae454c8434f7e76d0fd Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Fri, 9 Feb 2024 12:20:23 -0800 Subject: [PATCH 1/5] fuzz: ensures wazerolib test running Signed-off-by: Takeshi Yoneda --- Makefile | 1 + internal/integration_test/fuzz/predicate.sh | 2 +- .../integration_test/fuzz/wazerolib/nodiff.go | 8 +++++--- .../fuzz/wazerolib/nodiff_test.go | 15 ++++++++++----- .../fuzz/wazerolib/testdata/.keep | 0 .../fuzz/wazerolib/testdata/test.wasm | Bin 0 -> 666 bytes 6 files changed, 17 insertions(+), 9 deletions(-) delete mode 100644 internal/integration_test/fuzz/wazerolib/testdata/.keep create mode 100644 internal/integration_test/fuzz/wazerolib/testdata/test.wasm diff --git a/Makefile b/Makefile index 9017050180..ec87f0bd54 100644 --- a/Makefile +++ b/Makefile @@ -185,6 +185,7 @@ build.spectest.threads: test: @go test $(go_test_options) $$(go list ./... | grep -vE '$(spectest_v1_dir)|$(spectest_v2_dir)') @cd internal/version/testdata && go test $(go_test_options) ./... + @cd internal/integration_test/fuzz/wazerolib && WASM_BINARY_PATH=testdata/test.wasm go test $(go_test_options) ./... .PHONY: coverage # replace spaces with commas diff --git a/internal/integration_test/fuzz/predicate.sh b/internal/integration_test/fuzz/predicate.sh index de376eed6e..9a1bae4fe9 100755 --- a/internal/integration_test/fuzz/predicate.sh +++ b/internal/integration_test/fuzz/predicate.sh @@ -8,5 +8,5 @@ echo "Testing $WASM" export WASM_BINARY_PATH=$WASM # Run the test and reverse the exit code so that a non-zero exit code indicates interesting case. -./nodiff.test +./nodiff.test -test.run=TestReRunFailedRequireNoDiffCase exit $((! $?)) diff --git a/internal/integration_test/fuzz/wazerolib/nodiff.go b/internal/integration_test/fuzz/wazerolib/nodiff.go index 460f7206d2..ae20c5e410 100644 --- a/internal/integration_test/fuzz/wazerolib/nodiff.go +++ b/internal/integration_test/fuzz/wazerolib/nodiff.go @@ -154,10 +154,12 @@ func ensureMutableGlobalsMatch(compilerMod, interpreterMod api.Module, requireNo } if !ok { - if ig.Type.ValType == wasm.ValueTypeV128 { - es = append(es, fmt.Sprintf("mutable global[%d] value mismatch: (%v,%v) != (%v,%v)", i, cVal, cValHi, iVal, iValHi)) + if typ := ig.Type.ValType; typ == wasm.ValueTypeV128 { + es = append(es, fmt.Sprintf("\t[%d] %s: (%v,%v) != (%v,%v)", + i, wasm.ValueTypeName(wasm.ValueTypeV128), cVal, cValHi, iVal, iValHi)) } else { - es = append(es, fmt.Sprintf("mutable global[%d] value mismatch: %v != %v", i, cVal, iVal)) + es = append(es, fmt.Sprintf("\t[%d] %s: %v != %v", + i, wasm.ValueTypeName(typ), cVal, iVal)) } } } diff --git a/internal/integration_test/fuzz/wazerolib/nodiff_test.go b/internal/integration_test/fuzz/wazerolib/nodiff_test.go index 9807f7e748..7b51f46dde 100644 --- a/internal/integration_test/fuzz/wazerolib/nodiff_test.go +++ b/internal/integration_test/fuzz/wazerolib/nodiff_test.go @@ -60,7 +60,8 @@ func Test_ensureMutableGlobalsMatch(t *testing.T) { {Val: 11, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}}, }, }, - expErr: "mutable global[1] value mismatch: 10 != 11", + expErr: `mutable globals mismatch: + [1] i32: 10 != 11`, }, { name: "i64 match", @@ -93,7 +94,8 @@ func Test_ensureMutableGlobalsMatch(t *testing.T) { {Val: 1 << 63, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}}, }, }, - expErr: "mutable global[2] value mismatch: 4611686018427387904 != 9223372036854775808", + expErr: `mutable globals mismatch: + [2] i64: 4611686018427387904 != 9223372036854775808`, }, { name: "f32 match", @@ -124,7 +126,8 @@ func Test_ensureMutableGlobalsMatch(t *testing.T) { {Val: 11, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}}, }, }, - expErr: "mutable global[1] value mismatch: 10 != 11", + expErr: `mutable globals mismatch: + [1] f32: 10 != 11`, }, { name: "f64 match", @@ -157,7 +160,8 @@ func Test_ensureMutableGlobalsMatch(t *testing.T) { {Val: 1 << 63, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}}, }, }, - expErr: "mutable global[2] value mismatch: 4611686018427387904 != 9223372036854775808", + expErr: `mutable globals mismatch: + [2] f64: 4611686018427387904 != 9223372036854775808`, }, { @@ -191,7 +195,8 @@ func Test_ensureMutableGlobalsMatch(t *testing.T) { {Val: 1 << 62, ValHi: 1234, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}}, }, }, - expErr: "mutable global[2] value mismatch: (4611686018427387904,0) != (4611686018427387904,1234)", + expErr: `mutable globals mismatch: + [2] v128: (4611686018427387904,0) != (4611686018427387904,1234)`, }, } { t.Run(tc.name, func(t *testing.T) { diff --git a/internal/integration_test/fuzz/wazerolib/testdata/.keep b/internal/integration_test/fuzz/wazerolib/testdata/.keep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/internal/integration_test/fuzz/wazerolib/testdata/test.wasm b/internal/integration_test/fuzz/wazerolib/testdata/test.wasm new file mode 100644 index 0000000000000000000000000000000000000000..c0282923b775a2930d87dc7451283837a821f5ca GIT binary patch literal 666 zcmZQbEY4+QU|?WmXG~zMXR57XW@2PulV_=8bYkGHXLMxXu4Qxv$}@1+FuH(f5a4EK z0qNno&BAztg~5?=lS>U0z!}>d8Mh-ia2A}g4aBkm=|U9(iBKxU#l_{sfPjt+&KH5e z<;Q+6pDm6(eJ=K3OKNJsZop-sbNx}HHE_4V8Ay6urKernFef|*NeE(ae?LeFVhcRX zFjOJizfFZnnQ6BQvof;+1B-()lQJ_uEB9VyhE^2@WkwZ75Z Date: Fri, 9 Feb 2024 12:27:51 -0800 Subject: [PATCH 2/5] extern Signed-off-by: Takeshi Yoneda --- .../integration_test/fuzz/wazerolib/extern.go | 62 ++++++++++++++++++ .../integration_test/fuzz/wazerolib/lib.go | 3 - .../integration_test/fuzz/wazerolib/nodiff.go | 31 --------- .../fuzz/wazerolib/testdata/test.wasm | Bin 666 -> 72 bytes .../fuzz/wazerolib/validate.go | 27 -------- 5 files changed, 62 insertions(+), 61 deletions(-) create mode 100644 internal/integration_test/fuzz/wazerolib/extern.go diff --git a/internal/integration_test/fuzz/wazerolib/extern.go b/internal/integration_test/fuzz/wazerolib/extern.go new file mode 100644 index 0000000000..792530d7d3 --- /dev/null +++ b/internal/integration_test/fuzz/wazerolib/extern.go @@ -0,0 +1,62 @@ +package main + +import "C" +import ( + "reflect" + "unsafe" +) + +func main() {} + +// require_no_diff ensures that the behavior is the same between the compiler and the interpreter for any given binary. +// And if there's diff, this also saves the problematic binary and wat into testdata directory. +// +//export require_no_diff +func require_no_diff(binaryPtr uintptr, binarySize int, checkMemory bool) { + // TODO: use unsafe.Slice after flooring Go 1.20. + var wasmBin []byte + wasmHdr := (*reflect.SliceHeader)(unsafe.Pointer(&wasmBin)) + wasmHdr.Data = binaryPtr + wasmHdr.Len = binarySize + wasmHdr.Cap = binarySize + + failed := true + defer func() { + if failed { + // If the test fails, we save the binary and wat into testdata directory. + saveFailedBinary(wasmBin, "TestReRunFailedRequireNoDiffCase") + } + }() + + requireNoDiff(wasmBin, checkMemory, func(err error) { + if err != nil { + panic(err) + } + }) + + failed = false +} + +// validate accepts maybe-invalid Wasm module bytes and ensures that our validation phase works correctly +// as well as the compiler doesn't panic during compilation! +// +//export validate +func validate(binaryPtr uintptr, binarySize int) { + // TODO: use unsafe.Slice after flooring Go 1.20. + var wasmBin []byte + wasmHdr := (*reflect.SliceHeader)(unsafe.Pointer(&wasmBin)) + wasmHdr.Data = binaryPtr + wasmHdr.Len = binarySize + wasmHdr.Cap = binarySize + + failed := true + defer func() { + if failed { + // If the test fails, we save the binary and wat into testdata directory. + saveFailedBinary(wasmBin, "TestReRunFailedValidateCase") + } + }() + + tryCompile(wasmBin) + failed = false +} diff --git a/internal/integration_test/fuzz/wazerolib/lib.go b/internal/integration_test/fuzz/wazerolib/lib.go index f6a2bc7a7c..ca0620a297 100644 --- a/internal/integration_test/fuzz/wazerolib/lib.go +++ b/internal/integration_test/fuzz/wazerolib/lib.go @@ -1,6 +1,5 @@ package main -import "C" import ( "context" "crypto/sha256" @@ -19,8 +18,6 @@ import ( "github.com/tetratelabs/wazero/internal/wasm" ) -func main() {} - const failedCasesDir = "wazerolib/testdata" // saveFailedBinary writes binary and wat into failedCasesDir so that it is easy to reproduce the error. diff --git a/internal/integration_test/fuzz/wazerolib/nodiff.go b/internal/integration_test/fuzz/wazerolib/nodiff.go index ae20c5e410..037488bc89 100644 --- a/internal/integration_test/fuzz/wazerolib/nodiff.go +++ b/internal/integration_test/fuzz/wazerolib/nodiff.go @@ -1,12 +1,10 @@ package main -import "C" import ( "bytes" "context" "errors" "fmt" - "reflect" "sort" "strings" "unsafe" @@ -18,35 +16,6 @@ import ( "github.com/tetratelabs/wazero/internal/wasm" ) -// require_no_diff ensures that the behavior is the same between the compiler and the interpreter for any given binary. -// And if there's diff, this also saves the problematic binary and wat into testdata directory. -// -//export require_no_diff -func require_no_diff(binaryPtr uintptr, binarySize int, checkMemory bool) { - // TODO: use unsafe.Slice after flooring Go 1.20. - var wasmBin []byte - wasmHdr := (*reflect.SliceHeader)(unsafe.Pointer(&wasmBin)) - wasmHdr.Data = binaryPtr - wasmHdr.Len = binarySize - wasmHdr.Cap = binarySize - - failed := true - defer func() { - if failed { - // If the test fails, we save the binary and wat into testdata directory. - saveFailedBinary(wasmBin, "TestReRunFailedRequireNoDiffCase") - } - }() - - requireNoDiff(wasmBin, checkMemory, func(err error) { - if err != nil { - panic(err) - } - }) - - failed = false -} - // We haven't had public APIs for referencing all the imported entries from wazero.CompiledModule, // so we use the unsafe.Pointer and the internal memory layout to get the internal *wasm.Module // from wazero.CompiledFunction. This must be synced with the struct definition of wazero.compiledModule (internal one). diff --git a/internal/integration_test/fuzz/wazerolib/testdata/test.wasm b/internal/integration_test/fuzz/wazerolib/testdata/test.wasm index c0282923b775a2930d87dc7451283837a821f5ca..7ba12f9429a37b9fd62fdbd021c46cdf586b1aad 100644 GIT binary patch literal 72 zcmXBKu?>JA6h+bd6!;N(7jP0ckwi*pw6Kzi+))$jbI3;(Ag>MG;~+v%XYI+NLb=Y; Vc8Dg=!jqU?%e83w-jC*l+6#*63+Dg; literal 666 zcmZQbEY4+QU|?WmXG~zMXR57XW@2PulV_=8bYkGHXLMxXu4Qxv$}@1+FuH(f5a4EK z0qNno&BAztg~5?=lS>U0z!}>d8Mh-ia2A}g4aBkm=|U9(iBKxU#l_{sfPjt+&KH5e z<;Q+6pDm6(eJ=K3OKNJsZop-sbNx}HHE_4V8Ay6urKernFef|*NeE(ae?LeFVhcRX zFjOJizfFZnnQ6BQvof;+1B-()lQJ_uEB9VyhE^2@WkwZ75Z Date: Fri, 9 Feb 2024 12:29:36 -0800 Subject: [PATCH 3/5] fuzz Signed-off-by: Takeshi Yoneda --- .../integration_test/fuzz/wazerolib/extern.go | 78 +++++++++++++++++++ .../integration_test/fuzz/wazerolib/lib.go | 75 ------------------ 2 files changed, 78 insertions(+), 75 deletions(-) diff --git a/internal/integration_test/fuzz/wazerolib/extern.go b/internal/integration_test/fuzz/wazerolib/extern.go index 792530d7d3..9f5d9de636 100644 --- a/internal/integration_test/fuzz/wazerolib/extern.go +++ b/internal/integration_test/fuzz/wazerolib/extern.go @@ -2,8 +2,17 @@ package main import "C" import ( + "context" + "math" "reflect" + "strings" "unsafe" + + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/experimental/opt" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/testing/binaryencoding" + "github.com/tetratelabs/wazero/internal/wasm" ) func main() {} @@ -60,3 +69,72 @@ func validate(binaryPtr uintptr, binarySize int) { tryCompile(wasmBin) failed = false } + +//export test_signal_stack +func test_signal_stack() { + // (module + // (func (export "long_loop") + // (loop + // global.get 0 + // i32.eqz + // if ;; label = @1 + // unreachable + // end + // global.get 0 + // i32.const 1 + // i32.sub + // global.set 0 + // br 0 + // ) + // ) + // (global (;0;) (mut i32) i32.const 2147483648) + // ) + bin := binaryencoding.EncodeModule(&wasm.Module{ + TypeSection: []wasm.FunctionType{{}}, + FunctionSection: []wasm.Index{0}, + GlobalSection: []wasm.Global{{ + Type: wasm.GlobalType{ValType: wasm.ValueTypeI32, Mutable: true}, + Init: wasm.ConstantExpression{ + Opcode: wasm.OpcodeI32Const, + Data: leb128.EncodeInt32(math.MaxInt32), + }, + }}, + ExportSection: []wasm.Export{{Type: wasm.ExternTypeFunc, Name: "long_loop", Index: 0}}, + CodeSection: []wasm.Code{ + { + Body: []byte{ + wasm.OpcodeLoop, 0, + wasm.OpcodeGlobalGet, 0, + wasm.OpcodeI32Eqz, + wasm.OpcodeIf, 0, + wasm.OpcodeUnreachable, + wasm.OpcodeEnd, + wasm.OpcodeGlobalGet, 0, + wasm.OpcodeI32Const, 1, + wasm.OpcodeI32Sub, + wasm.OpcodeGlobalSet, 0, + wasm.OpcodeBr, 0, + wasm.OpcodeEnd, + wasm.OpcodeEnd, + }, + }, + }, + }) + ctx := context.Background() + config := opt.NewRuntimeConfigOptimizingCompiler() + r := wazero.NewRuntimeWithConfig(ctx, config) + module, err := r.Instantiate(ctx, bin) + if err != nil { + panic(err) + } + defer func() { + if err = module.Close(ctx); err != nil { + panic(err) + } + }() + + _, err = module.ExportedFunction("long_loop").Call(ctx) + if !strings.Contains(err.Error(), "unreachable") { + panic("long_loop should be unreachable") + } +} diff --git a/internal/integration_test/fuzz/wazerolib/lib.go b/internal/integration_test/fuzz/wazerolib/lib.go index ca0620a297..54bd13823a 100644 --- a/internal/integration_test/fuzz/wazerolib/lib.go +++ b/internal/integration_test/fuzz/wazerolib/lib.go @@ -1,21 +1,15 @@ package main import ( - "context" "crypto/sha256" _ "embed" "encoding/hex" "fmt" - "math" "os" "path" - "strings" "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/experimental/opt" - "github.com/tetratelabs/wazero/internal/leb128" - "github.com/tetratelabs/wazero/internal/testing/binaryencoding" - "github.com/tetratelabs/wazero/internal/wasm" ) const failedCasesDir = "wazerolib/testdata" @@ -59,72 +53,3 @@ func newCompilerConfig() wazero.RuntimeConfig { } return c } - -//export test_signal_stack -func test_signal_stack() { - // (module - // (func (export "long_loop") - // (loop - // global.get 0 - // i32.eqz - // if ;; label = @1 - // unreachable - // end - // global.get 0 - // i32.const 1 - // i32.sub - // global.set 0 - // br 0 - // ) - // ) - // (global (;0;) (mut i32) i32.const 2147483648) - // ) - bin := binaryencoding.EncodeModule(&wasm.Module{ - TypeSection: []wasm.FunctionType{{}}, - FunctionSection: []wasm.Index{0}, - GlobalSection: []wasm.Global{{ - Type: wasm.GlobalType{ValType: wasm.ValueTypeI32, Mutable: true}, - Init: wasm.ConstantExpression{ - Opcode: wasm.OpcodeI32Const, - Data: leb128.EncodeInt32(math.MaxInt32), - }, - }}, - ExportSection: []wasm.Export{{Type: wasm.ExternTypeFunc, Name: "long_loop", Index: 0}}, - CodeSection: []wasm.Code{ - { - Body: []byte{ - wasm.OpcodeLoop, 0, - wasm.OpcodeGlobalGet, 0, - wasm.OpcodeI32Eqz, - wasm.OpcodeIf, 0, - wasm.OpcodeUnreachable, - wasm.OpcodeEnd, - wasm.OpcodeGlobalGet, 0, - wasm.OpcodeI32Const, 1, - wasm.OpcodeI32Sub, - wasm.OpcodeGlobalSet, 0, - wasm.OpcodeBr, 0, - wasm.OpcodeEnd, - wasm.OpcodeEnd, - }, - }, - }, - }) - ctx := context.Background() - config := opt.NewRuntimeConfigOptimizingCompiler() - r := wazero.NewRuntimeWithConfig(ctx, config) - module, err := r.Instantiate(ctx, bin) - if err != nil { - panic(err) - } - defer func() { - if err = module.Close(ctx); err != nil { - panic(err) - } - }() - - _, err = module.ExportedFunction("long_loop").Call(ctx) - if !strings.Contains(err.Error(), "unreachable") { - panic("long_loop should be unreachable") - } -} From 314111001e05e25ebe26d740216e8570368eece4 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Fri, 9 Feb 2024 12:38:17 -0800 Subject: [PATCH 4/5] no cgo Signed-off-by: Takeshi Yoneda --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ec87f0bd54..917d1460d3 100644 --- a/Makefile +++ b/Makefile @@ -185,7 +185,7 @@ build.spectest.threads: test: @go test $(go_test_options) $$(go list ./... | grep -vE '$(spectest_v1_dir)|$(spectest_v2_dir)') @cd internal/version/testdata && go test $(go_test_options) ./... - @cd internal/integration_test/fuzz/wazerolib && WASM_BINARY_PATH=testdata/test.wasm go test $(go_test_options) ./... + @cd internal/integration_test/fuzz/wazerolib && CGO_ENABLED=0 WASM_BINARY_PATH=testdata/test.wasm go test $(go_test_options) ./... .PHONY: coverage # replace spaces with commas From 700c363f2eb479fa4f590c8a7de535b4e9a3450a Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Fri, 9 Feb 2024 12:41:31 -0800 Subject: [PATCH 5/5] no cgo Signed-off-by: Takeshi Yoneda --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 917d1460d3..eb87648e75 100644 --- a/Makefile +++ b/Makefile @@ -185,7 +185,7 @@ build.spectest.threads: test: @go test $(go_test_options) $$(go list ./... | grep -vE '$(spectest_v1_dir)|$(spectest_v2_dir)') @cd internal/version/testdata && go test $(go_test_options) ./... - @cd internal/integration_test/fuzz/wazerolib && CGO_ENABLED=0 WASM_BINARY_PATH=testdata/test.wasm go test $(go_test_options) ./... + @cd internal/integration_test/fuzz/wazerolib && CGO_ENABLED=0 WASM_BINARY_PATH=testdata/test.wasm go test ./... .PHONY: coverage # replace spaces with commas