github.com/tetratelabs/wazero@v1.2.1/internal/integration_test/fuzzcases/fuzzcases_test.go (about)

     1  package fuzzcases
     2  
     3  import (
     4  	"context"
     5  	"embed"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/tetratelabs/wazero"
    10  	"github.com/tetratelabs/wazero/api"
    11  	"github.com/tetratelabs/wazero/internal/platform"
    12  	"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
    13  	"github.com/tetratelabs/wazero/internal/testing/require"
    14  	"github.com/tetratelabs/wazero/internal/wasm"
    15  )
    16  
    17  var ctx = context.Background()
    18  
    19  //go:embed testdata/*.wasm
    20  var testcases embed.FS
    21  
    22  func getWasmBinary(t *testing.T, number int) []byte {
    23  	ret, err := testcases.ReadFile(fmt.Sprintf("testdata/%d.wasm", number))
    24  	require.NoError(t, err)
    25  	return ret
    26  }
    27  
    28  func runWithCompiler(t *testing.T, runner func(t *testing.T, r wazero.Runtime)) {
    29  	if !platform.CompilerSupported() {
    30  		return
    31  	}
    32  	t.Run("compiler", func(t *testing.T) {
    33  		r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigCompiler())
    34  		defer r.Close(ctx)
    35  		runner(t, r)
    36  	})
    37  }
    38  
    39  func runWithInterpreter(t *testing.T, runner func(t *testing.T, r wazero.Runtime)) {
    40  	t.Run("interpreter", func(t *testing.T) {
    41  		r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter())
    42  		defer r.Close(ctx)
    43  		runner(t, r)
    44  	})
    45  }
    46  
    47  func run(t *testing.T, runner func(t *testing.T, r wazero.Runtime)) {
    48  	runWithInterpreter(t, runner)
    49  	runWithCompiler(t, runner)
    50  }
    51  
    52  // Test695 requires two functions to exit with "out of bounds memory access" consistently across the implementations.
    53  func Test695(t *testing.T) {
    54  	run(t, func(t *testing.T, r wazero.Runtime) {
    55  		module, err := r.Instantiate(ctx, getWasmBinary(t, 695))
    56  		require.NoError(t, err)
    57  
    58  		_, err = module.ExportedFunction("i8x16s").Call(ctx)
    59  		require.NotNil(t, err)
    60  		require.Contains(t, err.Error(), "out of bounds memory access")
    61  
    62  		_, err = module.ExportedFunction("i16x8s").Call(ctx)
    63  		require.NotNil(t, err)
    64  		require.Contains(t, err.Error(), "out of bounds memory access")
    65  	})
    66  }
    67  
    68  func Test696(t *testing.T) {
    69  	functionNames := [4]string{
    70  		"select with 0 / after calling dummy",
    71  		"select with 0",
    72  		"typed select with 1 / after calling dummy",
    73  		"typed select with 1",
    74  	}
    75  
    76  	run(t, func(t *testing.T, r wazero.Runtime) {
    77  		module, err := r.Instantiate(ctx, getWasmBinary(t, 696))
    78  		require.NoError(t, err)
    79  
    80  		for _, name := range functionNames {
    81  			_, err := module.ExportedFunction(name).Call(ctx)
    82  			require.NoError(t, err)
    83  		}
    84  	})
    85  }
    86  
    87  // Test699 ensures that accessing element instances and data instances works
    88  // without crash even when the access happens in the nested function call.
    89  func Test699(t *testing.T) {
    90  	run(t, func(t *testing.T, r wazero.Runtime) {
    91  		defer r.Close(ctx)
    92  		_, err := r.Instantiate(ctx, getWasmBinary(t, 699))
    93  		require.NoError(t, err)
    94  	})
    95  }
    96  
    97  // Test701 requires two functions to exit with "out of bounds memory access" consistently across the implementations.
    98  func Test701(t *testing.T) {
    99  	run(t, func(t *testing.T, r wazero.Runtime) {
   100  		module, err := r.Instantiate(ctx, getWasmBinary(t, 701))
   101  		require.NoError(t, err)
   102  
   103  		_, err = module.ExportedFunction("i32.extend16_s").Call(ctx)
   104  		require.NotNil(t, err)
   105  		require.Contains(t, err.Error(), "out of bounds memory access")
   106  
   107  		_, err = module.ExportedFunction("i32.extend8_s").Call(ctx)
   108  		require.NotNil(t, err)
   109  		require.Contains(t, err.Error(), "out of bounds memory access")
   110  	})
   111  }
   112  
   113  func Test704(t *testing.T) {
   114  	run(t, func(t *testing.T, r wazero.Runtime) {
   115  		_, err := r.Instantiate(ctx, getWasmBinary(t, 704))
   116  		require.NoError(t, err)
   117  	})
   118  }
   119  
   120  func Test708(t *testing.T) {
   121  	run(t, func(t *testing.T, r wazero.Runtime) {
   122  		_, err := r.Instantiate(ctx, getWasmBinary(t, 708))
   123  		require.NotNil(t, err)
   124  		require.Contains(t, err.Error(), "out of bounds memory access")
   125  	})
   126  }
   127  
   128  func Test709(t *testing.T) {
   129  	run(t, func(t *testing.T, r wazero.Runtime) {
   130  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 709))
   131  		require.NoError(t, err)
   132  
   133  		f := mod.ExportedFunction("f64x2.promote_low_f32x4")
   134  		require.NotNil(t, f)
   135  		res, err := f.Call(ctx)
   136  		require.NoError(t, err)
   137  
   138  		require.NotEqual(t, uint64(0), res[0])
   139  		require.NotEqual(t, uint64(0), res[1])
   140  	})
   141  }
   142  
   143  func Test715(t *testing.T) {
   144  	run(t, func(t *testing.T, r wazero.Runtime) {
   145  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 715))
   146  		require.NoError(t, err)
   147  
   148  		f := mod.ExportedFunction("select on conditional value after table.size")
   149  		require.NotNil(t, f)
   150  		res, err := f.Call(ctx)
   151  		require.NoError(t, err)
   152  
   153  		require.Equal(t, uint64(1), res[0])
   154  	})
   155  }
   156  
   157  func Test716(t *testing.T) {
   158  	run(t, func(t *testing.T, r wazero.Runtime) {
   159  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 716))
   160  		require.NoError(t, err)
   161  
   162  		f := mod.ExportedFunction("select on ref.func")
   163  		require.NotNil(t, f)
   164  		res, err := f.Call(ctx)
   165  		require.NoError(t, err)
   166  
   167  		require.Equal(t, uint64(1), res[0])
   168  	})
   169  }
   170  
   171  func Test717(t *testing.T) {
   172  	run(t, func(t *testing.T, r wazero.Runtime) {
   173  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 717))
   174  		require.NoError(t, err)
   175  
   176  		f := mod.ExportedFunction("vectors")
   177  		require.NotNil(t, f)
   178  		res, err := f.Call(ctx)
   179  		require.NoError(t, err)
   180  
   181  		const expectedLen = 35
   182  		require.Equal(t, expectedLen, len(res))
   183  		for i := 0; i < expectedLen; i++ {
   184  			require.Equal(t, uint64(i), res[i])
   185  		}
   186  	})
   187  }
   188  
   189  func Test718(t *testing.T) {
   190  	run(t, func(t *testing.T, r wazero.Runtime) {
   191  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 718))
   192  		require.NoError(t, err)
   193  
   194  		f := mod.ExportedFunction("v128.load_zero on the ceil")
   195  		require.NotNil(t, f)
   196  		_, err = f.Call(ctx)
   197  		require.NoError(t, err)
   198  	})
   199  }
   200  
   201  func Test719(t *testing.T) {
   202  	run(t, func(t *testing.T, r wazero.Runtime) {
   203  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 719))
   204  		require.NoError(t, err)
   205  
   206  		f := mod.ExportedFunction("require unreachable")
   207  		require.NotNil(t, f)
   208  		_, err = f.Call(ctx)
   209  		require.Error(t, err)
   210  		require.Contains(t, err.Error(), "wasm error: unreachable\nwasm stack trace:")
   211  	})
   212  }
   213  
   214  func Test720(t *testing.T) {
   215  	run(t, func(t *testing.T, r wazero.Runtime) {
   216  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 720))
   217  		require.NoError(t, err)
   218  
   219  		f := mod.ExportedFunction("access memory after table.grow")
   220  		require.NotNil(t, f)
   221  		res, err := f.Call(ctx)
   222  		require.NoError(t, err)
   223  		require.Equal(t, uint32(0xffffffff), uint32(res[0]))
   224  	})
   225  }
   226  
   227  func Test721(t *testing.T) {
   228  	run(t, func(t *testing.T, r wazero.Runtime) {
   229  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 721))
   230  		require.NoError(t, err)
   231  
   232  		f := mod.ExportedFunction("conditional before elem.drop")
   233  		require.NotNil(t, f)
   234  		ret, err := f.Call(ctx)
   235  		require.NoError(t, err)
   236  
   237  		require.Equal(t, uint64(1), ret[0])
   238  	})
   239  }
   240  
   241  func Test722(t *testing.T) {
   242  	run(t, func(t *testing.T, r wazero.Runtime) {
   243  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 722))
   244  		require.NoError(t, err)
   245  
   246  		f := mod.ExportedFunction("conditional before data.drop")
   247  		require.NotNil(t, f)
   248  		ret, err := f.Call(ctx)
   249  		require.NoError(t, err)
   250  
   251  		require.Equal(t, uint64(1), ret[0])
   252  	})
   253  }
   254  
   255  func Test725(t *testing.T) {
   256  	functions := []string{"i32.load8_s", "i32.load16_s"}
   257  	run(t, func(t *testing.T, r wazero.Runtime) {
   258  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 725))
   259  		require.NoError(t, err)
   260  
   261  		for _, fn := range functions {
   262  			f := mod.ExportedFunction(fn)
   263  			require.NotNil(t, f)
   264  			_, err := f.Call(ctx)
   265  			require.Error(t, err)
   266  			require.Contains(t, err.Error(), "out of bounds memory")
   267  		}
   268  	})
   269  }
   270  
   271  // Test730 ensures that the vector min/max operations comply with the spec wrt sign bits of zeros:
   272  //
   273  //   - min(0, 0) = 0, min(-0, 0) = -0, min(0, -0) = -0, min(-0, -0) = -0
   274  //   - max(0, 0) = 0, max(-0, 0) =  0, max(0, -0) =  0, max(-0, -0) = -0
   275  func Test730(t *testing.T) {
   276  	tests := []struct {
   277  		name string
   278  		exp  [2]uint64
   279  	}{
   280  		{name: "f32x4.max", exp: [2]uint64{0x80000000 << 32, 0x00000000}},
   281  		{name: "f32x4.min", exp: [2]uint64{0x80000000, 0x80000000<<32 | 0x80000000}},
   282  		{name: "f64x2.max", exp: [2]uint64{0, 0}},
   283  		{name: "f64x2.min", exp: [2]uint64{1 << 63, 1 << 63}},
   284  		{name: "f64x2.max/mix", exp: [2]uint64{0, 1 << 63}},
   285  		{name: "f64x2.min/mix", exp: [2]uint64{1 << 63, 0}},
   286  	}
   287  
   288  	run(t, func(t *testing.T, r wazero.Runtime) {
   289  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 730))
   290  		require.NoError(t, err)
   291  
   292  		for _, tc := range tests {
   293  			t.Run(tc.name, func(t *testing.T) {
   294  				f := mod.ExportedFunction(tc.name)
   295  				require.NotNil(t, f)
   296  				actual, err := f.Call(ctx)
   297  				require.NoError(t, err)
   298  				require.Equal(t, tc.exp[:], actual)
   299  			})
   300  		}
   301  	})
   302  }
   303  
   304  func Test733(t *testing.T) {
   305  	run(t, func(t *testing.T, r wazero.Runtime) {
   306  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 733))
   307  		require.NoError(t, err)
   308  
   309  		name := "out of bounds"
   310  		t.Run(name, func(t *testing.T) {
   311  			f := mod.ExportedFunction(name)
   312  			require.NotNil(t, f)
   313  			_, err = f.Call(ctx)
   314  			require.Error(t, err)
   315  			require.Contains(t, err.Error(), "out of bounds memory")
   316  		})
   317  
   318  		name = "store higher offset"
   319  		t.Run(name, func(t *testing.T) {
   320  			if testing.Short() {
   321  				// Note: this case uses large memory space, so can be slow like 1 to 2 seconds even without -race.
   322  				// The reason is that this test requires roughly 2GB of in-Wasm memory.
   323  				t.SkipNow()
   324  			}
   325  			f := mod.ExportedFunction(name)
   326  			require.NotNil(t, f)
   327  			_, err = f.Call(ctx)
   328  			require.NoError(t, err)
   329  
   330  			mem := mod.Memory()
   331  			require.NotNil(t, mem)
   332  
   333  			v, ok := mem.ReadUint64Le(0x80000100)
   334  			require.True(t, ok)
   335  			require.Equal(t, uint64(0xffffffffffffffff), v)
   336  		})
   337  	})
   338  }
   339  
   340  func Test873(t *testing.T) {
   341  	run(t, func(t *testing.T, r wazero.Runtime) {
   342  		_, err := r.Instantiate(ctx, getWasmBinary(t, 873))
   343  		require.NoError(t, err)
   344  	})
   345  }
   346  
   347  func Test874(t *testing.T) {
   348  	run(t, func(t *testing.T, r wazero.Runtime) {
   349  		_, err := r.Instantiate(ctx, getWasmBinary(t, 874))
   350  		require.NoError(t, err)
   351  	})
   352  }
   353  
   354  func Test888(t *testing.T) {
   355  	// This tests that importing FuncRef type globals and using it as an initialization of the locally-defined
   356  	// FuncRef global works fine.
   357  	run(t, func(t *testing.T, r wazero.Runtime) {
   358  		imported := binaryencoding.EncodeModule(&wasm.Module{
   359  			MemorySection: &wasm.Memory{Min: 0, Max: 5, IsMaxEncoded: true},
   360  			GlobalSection: []wasm.Global{
   361  				{
   362  					Type: wasm.GlobalType{
   363  						ValType: wasm.ValueTypeFuncref,
   364  						Mutable: false,
   365  					},
   366  					Init: wasm.ConstantExpression{
   367  						Opcode: wasm.OpcodeRefNull,
   368  						Data:   []byte{wasm.ValueTypeFuncref},
   369  					},
   370  				},
   371  			},
   372  			ExportSection: []wasm.Export{
   373  				{Name: "", Type: wasm.ExternTypeGlobal, Index: 0},
   374  				{Name: "s", Type: wasm.ExternTypeMemory, Index: 0},
   375  			},
   376  		})
   377  
   378  		_, err := r.InstantiateWithConfig(ctx, imported, wazero.NewModuleConfig().WithName("host"))
   379  		require.NoError(t, err)
   380  
   381  		_, err = r.InstantiateWithConfig(ctx, getWasmBinary(t, 888),
   382  			wazero.NewModuleConfig().WithName("test"))
   383  		require.NoError(t, err)
   384  	})
   385  }
   386  
   387  func Test1054(t *testing.T) {
   388  	if !platform.CompilerSupported() {
   389  		return
   390  	}
   391  
   392  	modules := make([]api.Module, 0, 2)
   393  	run(t, func(t *testing.T, r wazero.Runtime) {
   394  		mod, err := r.Instantiate(ctx, getWasmBinary(t, 1054))
   395  		require.NoError(t, err)
   396  		modules = append(modules, mod)
   397  	})
   398  
   399  	// Checks if the memory state is the same between engines.
   400  	require.Equal(t,
   401  		modules[0].Memory().(*wasm.MemoryInstance).Buffer,
   402  		modules[1].Memory().(*wasm.MemoryInstance).Buffer,
   403  	)
   404  }