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 }