diff --git a/api/wasm.go b/api/wasm.go index d6a0d796ab..6cb86e111d 100644 --- a/api/wasm.go +++ b/api/wasm.go @@ -563,7 +563,7 @@ type Memory interface { // has 1 page: 65536 // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefsyntax-instr-memorymathsfmemorysize%E2%91%A0 - Size() uint32 + Size() uint64 // Grow increases memory by the delta in pages (65536 bytes per page). // The return val is the previous memory size in pages, or false if the @@ -635,7 +635,7 @@ type Memory interface { // shared. Those who need a stable view must set Wasm memory min=max, or // use wazero.RuntimeConfig WithMemoryCapacityPages to ensure max is always // allocated. - Read(offset, byteCount uint32) ([]byte, bool) + Read(offset uint32, byteCount uint64) ([]byte, bool) // WriteByte writes a single byte to the underlying buffer at the offset in or returns false if out of range. WriteByte(offset uint32, v byte) bool diff --git a/builder.go b/builder.go index f64afabdf0..83798f5a5f 100644 --- a/builder.go +++ b/builder.go @@ -2,9 +2,11 @@ package wazero import ( "context" + "fmt" "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm/binary" ) // HostFunctionBuilder defines a host function (in Go), so that a @@ -182,6 +184,35 @@ type HostFunctionBuilder interface { type HostModuleBuilder interface { // Note: until golang/go#5860, we can't use example tests to embed code in interface godocs. + // ExportMemory adds linear memory, which a WebAssembly module can import and become available via api.Memory. + // If a memory is already exported with the same name, this overwrites it. + // + // # Parameters + // + // - name - the name to export. Ex "memory" for wasi_snapshot_preview1.ModuleSnapshotPreview1 + // - minPages - the possibly zero initial size in pages (65536 bytes per page). + // + // For example, the WebAssembly 1.0 Text Format below is the equivalent of this builder method: + // // (memory (export "memory") 1) + // builder.ExportMemory(1) + // + // # Notes + // + // - This is allowed to grow to (4GiB) limited by api.MemorySizer. To bound it, use ExportMemoryWithMax. + // - Version 1.0 (20191205) of the WebAssembly spec allows at most one memory per module. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-section%E2%91%A0 + ExportMemory(name string, minPages uint32) HostModuleBuilder + + // ExportMemoryWithMax is like ExportMemory, but can prevent overuse of memory. + // + // For example, the WebAssembly 1.0 Text Format below is the equivalent of this builder method: + // // (memory (export "memory") 1 1) + // builder.ExportMemoryWithMax(1, 1) + // + // Note: api.MemorySizer determines the capacity. + ExportMemoryWithMax(name string, minPages, maxPages uint32) HostModuleBuilder + // NewFunctionBuilder begins the definition of a host function. NewFunctionBuilder() HostFunctionBuilder @@ -218,6 +249,7 @@ type hostModuleBuilder struct { moduleName string exportNames []string nameToHostFunc map[string]*wasm.HostFunc + nameToMemory map[string]*wasm.Memory } // NewHostModuleBuilder implements Runtime.NewHostModuleBuilder @@ -226,6 +258,7 @@ func (r *runtime) NewHostModuleBuilder(moduleName string) HostModuleBuilder { r: r, moduleName: moduleName, nameToHostFunc: map[string]*wasm.HostFunc{}, + nameToMemory: map[string]*wasm.Memory{}, } } @@ -299,6 +332,18 @@ func (h *hostFunctionBuilder) Export(exportName string) HostModuleBuilder { return h.b } +// ExportMemory implements ModuleBuilder.ExportMemory +func (b *hostModuleBuilder) ExportMemory(name string, minPages uint32) HostModuleBuilder { + b.nameToMemory[name] = &wasm.Memory{Min: minPages} + return b +} + +// ExportMemoryWithMax implements ModuleBuilder.ExportMemoryWithMax +func (b *hostModuleBuilder) ExportMemoryWithMax(name string, minPages, maxPages uint32) HostModuleBuilder { + b.nameToMemory[name] = &wasm.Memory{Min: minPages, Max: maxPages, IsMaxEncoded: true} + return b +} + // ExportHostFunc implements wasm.HostFuncExporter func (b *hostModuleBuilder) ExportHostFunc(fn *wasm.HostFunc) { if _, ok := b.nameToHostFunc[fn.ExportName]; !ok { // add a new name @@ -314,7 +359,19 @@ func (b *hostModuleBuilder) NewFunctionBuilder() HostFunctionBuilder { // Compile implements HostModuleBuilder.Compile func (b *hostModuleBuilder) Compile(ctx context.Context) (CompiledModule, error) { - module, err := wasm.NewHostModule(b.moduleName, b.exportNames, b.nameToHostFunc, b.r.enabledFeatures) + // Verify the maximum limit here, so we don't have to pass it to wasm.NewHostModule + for name, mem := range b.nameToMemory { + var maxP *uint32 + if mem.IsMaxEncoded { + maxP = &mem.Max + } + mem.Min, mem.Cap, mem.Max = binary.NewMemorySizer(b.r.memoryLimitPages, b.r.memoryCapacityFromMax)(mem.Min, maxP) + if err := mem.Validate(b.r.memoryLimitPages); err != nil { + return nil, fmt.Errorf("memory[%s] %v", name, err) + } + } + + module, err := wasm.NewHostModule(b.moduleName, b.exportNames, b.nameToHostFunc, b.nameToMemory, b.r.enabledFeatures) if err != nil { return nil, err } else if err = module.Validate(b.r.enabledFeatures); err != nil { @@ -327,6 +384,8 @@ func (b *hostModuleBuilder) Compile(ctx context.Context) (CompiledModule, error) return nil, err } + module.BuildMemoryDefinitions() + if err = b.r.store.Engine.CompileModule(ctx, module, listeners, false); err != nil { return nil, err } diff --git a/examples/allocation/rust/greet.go b/examples/allocation/rust/greet.go index 3d19eec3e2..e416d6bd7c 100644 --- a/examples/allocation/rust/greet.go +++ b/examples/allocation/rust/greet.go @@ -91,7 +91,7 @@ func main() { defer deallocate.Call(ctx, uint64(greetingPtr), uint64(greetingSize)) // The pointer is a linear memory offset, which is where we write the name. - if bytes, ok := mod.Memory().Read(greetingPtr, greetingSize); !ok { + if bytes, ok := mod.Memory().Read(greetingPtr, uint64(greetingSize)); !ok { log.Panicf("Memory.Read(%d, %d) out of range of memory size %d", greetingPtr, greetingSize, mod.Memory().Size()) } else { @@ -100,7 +100,7 @@ func main() { } func logString(ctx context.Context, m api.Module, offset, byteCount uint32) { - buf, ok := m.Memory().Read(offset, byteCount) + buf, ok := m.Memory().Read(offset, uint64(byteCount)) if !ok { log.Panicf("Memory.Read(%d, %d) out of range", offset, byteCount) } diff --git a/examples/allocation/tinygo/greet.go b/examples/allocation/tinygo/greet.go index 22d76d64c5..fcebeb197e 100644 --- a/examples/allocation/tinygo/greet.go +++ b/examples/allocation/tinygo/greet.go @@ -106,7 +106,7 @@ func main() { } // The pointer is a linear memory offset, which is where we write the name. - if bytes, ok := mod.Memory().Read(greetingPtr, greetingSize); !ok { + if bytes, ok := mod.Memory().Read(greetingPtr, uint64(greetingSize)); !ok { log.Panicf("Memory.Read(%d, %d) out of range of memory size %d", greetingPtr, greetingSize, mod.Memory().Size()) } else { @@ -115,7 +115,7 @@ func main() { } func logString(_ context.Context, m api.Module, offset, byteCount uint32) { - buf, ok := m.Memory().Read(offset, byteCount) + buf, ok := m.Memory().Read(offset, uint64(byteCount)) if !ok { log.Panicf("Memory.Read(%d, %d) out of range", offset, byteCount) } diff --git a/examples/allocation/zig/greet.go b/examples/allocation/zig/greet.go index 467dc8e0d8..7ed6bac59d 100644 --- a/examples/allocation/zig/greet.go +++ b/examples/allocation/zig/greet.go @@ -98,7 +98,7 @@ func run() error { greetingPtr := uint32(ptrSize[0] >> 32) greetingSize := uint32(ptrSize[0]) // The pointer is a linear memory offset, which is where we write the name. - if bytes, ok := mod.Memory().Read(greetingPtr, greetingSize); !ok { + if bytes, ok := mod.Memory().Read(greetingPtr, uint64(greetingSize)); !ok { return fmt.Errorf("Memory.Read(%d, %d) out of range of memory size %d", greetingPtr, greetingSize, mod.Memory().Size()) } else { @@ -109,7 +109,7 @@ func run() error { } func logString(_ context.Context, m api.Module, offset, byteCount uint32) { - buf, ok := m.Memory().Read(offset, byteCount) + buf, ok := m.Memory().Read(offset, uint64(byteCount)) if !ok { log.Panicf("Memory.Read(%d, %d) out of range", offset, byteCount) } diff --git a/experimental/wazerotest/wazerotest.go b/experimental/wazerotest/wazerotest.go index bfbddf786d..252334b44f 100644 --- a/experimental/wazerotest/wazerotest.go +++ b/experimental/wazerotest/wazerotest.go @@ -507,8 +507,8 @@ func (m *Memory) Definition() api.MemoryDefinition { return memoryDefinition{memory: m} } -func (m *Memory) Size() uint32 { - return uint32(len(m.Bytes)) +func (m *Memory) Size() uint64 { + return uint64(len(m.Bytes)) } func (m *Memory) Grow(deltaPages uint32) (previousPages uint32, ok bool) { @@ -561,11 +561,11 @@ func (m *Memory) ReadFloat64Le(offset uint32) (float64, bool) { return math.Float64frombits(v), ok } -func (m *Memory) Read(offset, length uint32) ([]byte, bool) { +func (m *Memory) Read(offset uint32, length uint64) ([]byte, bool) { if m.isOutOfRange(offset, length) { return nil, false } - return m.Bytes[offset : offset+length : offset+length], true + return m.Bytes[offset : uint64(offset)+length : uint64(offset)+length], true } func (m *Memory) WriteByte(offset uint32, value byte) bool { @@ -609,7 +609,7 @@ func (m *Memory) WriteFloat64Le(offset uint32, value float64) bool { } func (m *Memory) Write(offset uint32, value []byte) bool { - if m.isOutOfRange(offset, uint32(len(value))) { + if m.isOutOfRange(offset, uint64(len(value))) { return false } copy(m.Bytes[offset:], value) @@ -617,15 +617,16 @@ func (m *Memory) Write(offset uint32, value []byte) bool { } func (m *Memory) WriteString(offset uint32, value string) bool { - if m.isOutOfRange(offset, uint32(len(value))) { + if m.isOutOfRange(offset, uint64(len(value))) { return false } copy(m.Bytes[offset:], value) return true } -func (m *Memory) isOutOfRange(offset, length uint32) bool { +func (m *Memory) isOutOfRange(_offset uint32, length uint64) bool { size := m.Size() + offset := uint64(_offset) return offset >= size || length > size || offset > (size-length) } diff --git a/imports/assemblyscript/assemblyscript.go b/imports/assemblyscript/assemblyscript.go index 5cbe605bbd..8f2ac445a2 100644 --- a/imports/assemblyscript/assemblyscript.go +++ b/imports/assemblyscript/assemblyscript.go @@ -305,7 +305,7 @@ func readAssemblyScriptString(mem api.Memory, offset uint32) (string, bool) { if !ok || byteCount%2 != 0 { return "", false } - buf, ok := mem.Read(offset, byteCount) + buf, ok := mem.Read(offset, uint64(byteCount)) if !ok { return "", false } diff --git a/imports/wasi_snapshot_preview1/args_test.go b/imports/wasi_snapshot_preview1/args_test.go index fb30640fe5..bbc6b00bd3 100644 --- a/imports/wasi_snapshot_preview1/args_test.go +++ b/imports/wasi_snapshot_preview1/args_test.go @@ -32,7 +32,7 @@ func Test_argsGet(t *testing.T) { <== errno=ESUCCESS `, "\n"+log.String()) - actual, ok := mod.Memory().Read(argvBuf-1, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(argvBuf-1, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) } @@ -41,7 +41,7 @@ func Test_argsGet_Errors(t *testing.T) { mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithArgs("a", "bc")) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) validAddress := uint32(0) // arbitrary tests := []struct { @@ -124,7 +124,7 @@ func Test_argsSizesGet(t *testing.T) { <== errno=ESUCCESS `, "\n"+log.String()) - actual, ok := mod.Memory().Read(resultArgc-1, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(resultArgc-1, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) } @@ -133,7 +133,7 @@ func Test_argsSizesGet_Errors(t *testing.T) { mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithArgs("a", "bc")) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) validAddress := uint32(0) // arbitrary valid address as arguments to args_sizes_get. We chose 0 here. tests := []struct { diff --git a/imports/wasi_snapshot_preview1/clock_test.go b/imports/wasi_snapshot_preview1/clock_test.go index 87879da303..dce231a029 100644 --- a/imports/wasi_snapshot_preview1/clock_test.go +++ b/imports/wasi_snapshot_preview1/clock_test.go @@ -63,7 +63,7 @@ func Test_clockResGet(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.ClockResGetName, uint64(tc.clockID), uint64(resultResolution)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(uint32(resultResolution-1), uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(uint32(resultResolution-1), uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) }) @@ -170,7 +170,7 @@ func Test_clockTimeGet(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.ClockTimeGetName, uint64(tc.clockID), 0 /* TODO: precision */, uint64(resultTimestamp)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(uint32(resultTimestamp-1), uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(uint32(resultTimestamp-1), uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) }) @@ -259,7 +259,7 @@ func Test_clockTimeGet_Errors(t *testing.T) { mod, r, log := requireProxyModule(t, wazero.NewModuleConfig()) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) tests := []struct { name string diff --git a/imports/wasi_snapshot_preview1/environ_test.go b/imports/wasi_snapshot_preview1/environ_test.go index 0ba8efae29..62a2d4c872 100644 --- a/imports/wasi_snapshot_preview1/environ_test.go +++ b/imports/wasi_snapshot_preview1/environ_test.go @@ -34,7 +34,7 @@ func Test_environGet(t *testing.T) { <== errno=ESUCCESS `, "\n"+log.String()) - actual, ok := mod.Memory().Read(resultEnvironBuf-1, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(resultEnvironBuf-1, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) } @@ -44,7 +44,7 @@ func Test_environGet_Errors(t *testing.T) { WithEnv("a", "bc").WithEnv("b", "cd")) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) validAddress := uint32(0) // arbitrary valid address as arguments to environ_get. We chose 0 here. tests := []struct { @@ -128,7 +128,7 @@ func Test_environSizesGet(t *testing.T) { <== errno=ESUCCESS `, "\n"+log.String()) - actual, ok := mod.Memory().Read(resultEnvironc-1, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(resultEnvironc-1, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) } @@ -138,7 +138,7 @@ func Test_environSizesGet_Errors(t *testing.T) { WithEnv("a", "b").WithEnv("b", "cd")) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) validAddress := uint32(0) // arbitrary tests := []struct { diff --git a/imports/wasi_snapshot_preview1/fs.go b/imports/wasi_snapshot_preview1/fs.go index 384036a275..7ae2aef97d 100644 --- a/imports/wasi_snapshot_preview1/fs.go +++ b/imports/wasi_snapshot_preview1/fs.go @@ -800,13 +800,13 @@ func fdReadOrPread(mod api.Module, params []uint64, isPread bool) experimentalsy func readv(mem api.Memory, iovs uint32, iovsCount uint32, reader func(buf []byte) (nread int, errno experimentalsys.Errno)) (uint32, experimentalsys.Errno) { var nread uint32 - iovsStop := iovsCount << 3 // iovsCount * 8 + iovsStop := uint64(iovsCount) * 8 iovsBuf, ok := mem.Read(iovs, iovsStop) if !ok { return 0, experimentalsys.EFAULT } - for iovsPos := uint32(0); iovsPos < iovsStop; iovsPos += 8 { + for iovsPos := uint64(0); iovsPos < iovsStop; iovsPos += 8 { offset := le.Uint32(iovsBuf[iovsPos:]) l := le.Uint32(iovsBuf[iovsPos+4:]) @@ -814,7 +814,7 @@ func readv(mem api.Memory, iovs uint32, iovsCount uint32, reader func(buf []byte continue } - b, ok := mem.Read(offset, l) + b, ok := mem.Read(offset, uint64(l)) if !ok { return 0, experimentalsys.EFAULT } @@ -917,7 +917,7 @@ func fdReaddirFn(_ context.Context, mod api.Module, params []uint64) experimenta // ^^ yes this can overflow to negative, which means our implementation // doesn't support writing greater than max int64 entries. - buf, ok := mem.Read(buf, bufToWrite) + buf, ok := mem.Read(buf, uint64(bufToWrite)) if !ok { return experimentalsys.EFAULT } @@ -1284,17 +1284,17 @@ func fdWriteOrPwrite(mod api.Module, params []uint64, isPwrite bool) experimenta func writev(mem api.Memory, iovs uint32, iovsCount uint32, writer func(buf []byte) (n int, errno experimentalsys.Errno)) (uint32, experimentalsys.Errno) { var nwritten uint32 - iovsStop := iovsCount << 3 // iovsCount * 8 + iovsStop := uint64(iovsCount) * 8 iovsBuf, ok := mem.Read(iovs, iovsStop) if !ok { return 0, experimentalsys.EFAULT } - for iovsPos := uint32(0); iovsPos < iovsStop; iovsPos += 8 { + for iovsPos := uint64(0); iovsPos < iovsStop; iovsPos += 8 { offset := le.Uint32(iovsBuf[iovsPos:]) l := le.Uint32(iovsBuf[iovsPos+4:]) - b, ok := mem.Read(offset, l) + b, ok := mem.Read(offset, uint64(l)) if !ok { return 0, experimentalsys.EFAULT } @@ -1645,7 +1645,7 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) experimental // See https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/sources/at_fdcwd.c // See https://linux.die.net/man/2/openat func atPath(fsc *sys.FSContext, mem api.Memory, fd int32, p, pathLen uint32) (experimentalsys.FS, string, experimentalsys.Errno) { - b, ok := mem.Read(p, pathLen) + b, ok := mem.Read(p, uint64(pathLen)) if !ok { return nil, "", experimentalsys.EFAULT } @@ -1946,12 +1946,12 @@ func pathSymlinkFn(_ context.Context, mod api.Module, params []uint64) experimen return experimentalsys.EINVAL } - oldPathBuf, ok := mem.Read(oldPath, oldPathLen) + oldPathBuf, ok := mem.Read(oldPath, uint64(oldPathLen)) if !ok { return experimentalsys.EFAULT } - newPathBuf, ok := mem.Read(newPath, newPathLen) + newPathBuf, ok := mem.Read(newPath, uint64(newPathLen)) if !ok { return experimentalsys.EFAULT } diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go index 04fe783c14..3d12f29d75 100644 --- a/imports/wasi_snapshot_preview1/fs_test.go +++ b/imports/wasi_snapshot_preview1/fs_test.go @@ -233,7 +233,7 @@ func Test_fdFdstatGet(t *testing.T) { file, dir := "animals.txt", "sub" mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFS(fstest.FS)) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) // open both paths without using WASI fsc := mod.(*wasm.ModuleInstance).Sys.FS() @@ -380,7 +380,7 @@ func Test_fdFdstatGet(t *testing.T) { requireErrnoResult(t, tc.expectedErrno, mod, wasip1.FdFdstatGetName, uint64(tc.fd), uint64(tc.resultFdstat)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) }) @@ -472,7 +472,7 @@ func Test_fdFdstatGet_StdioNonblock(t *testing.T) { requireErrnoResult(t, tc.expectedErrno, mod, wasip1.FdFdstatGetName, uint64(tc.fd), uint64(tc.resultFdstat)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) }) @@ -659,7 +659,7 @@ func Test_fdFilestatGet(t *testing.T) { file, dir := "animals.txt", "sub" mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFS(fstest.FS)) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) // open both paths without using WASI fsc := mod.(*wasm.ModuleInstance).Sys.FS() @@ -822,7 +822,7 @@ func Test_fdFilestatGet(t *testing.T) { requireErrnoResult(t, tc.expectedErrno, mod, wasip1.FdFilestatGetName, uint64(tc.fd), uint64(tc.resultFilestat)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) }) @@ -1160,7 +1160,7 @@ func Test_fdPread(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdPreadName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(tc.offset), uint64(resultNread)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) }) @@ -1200,7 +1200,7 @@ func Test_fdPread_offset(t *testing.T) { require.True(t, ok) requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdPreadName, uint64(fd), uint64(iovs), uint64(iovsCount), 2, uint64(resultNread)) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) @@ -1217,7 +1217,7 @@ func Test_fdPread_offset(t *testing.T) { ) requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdReadName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultNread)) - actual, ok = mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok = mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) @@ -1388,7 +1388,7 @@ func Test_fdPrestatGet(t *testing.T) { <== (prestat={pr_name_len=1},errno=ESUCCESS) `, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) } @@ -1397,7 +1397,7 @@ func Test_fdPrestatGet_Errors(t *testing.T) { mod, dirFD, log, r := requireOpenFile(t, t.TempDir(), "tmp", nil, true) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) tests := []struct { name string fd int32 @@ -1468,7 +1468,7 @@ func Test_fdPrestatDirName(t *testing.T) { <== (path=,errno=ESUCCESS) `, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) } @@ -1477,7 +1477,7 @@ func Test_fdPrestatDirName_Errors(t *testing.T) { mod, dirFD, log, r := requireOpenFile(t, t.TempDir(), "tmp", nil, true) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) maskMemory(t, mod, 10) validAddress := uint32(0) // Arbitrary valid address as arguments to fd_prestat_dir_name. We chose 0 here. @@ -1634,7 +1634,7 @@ func Test_fdPwrite(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdPwriteName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(tc.offset), uint64(resultNwritten)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) @@ -1680,7 +1680,7 @@ func Test_fdPwrite_offset(t *testing.T) { // Write the last half first, to offset 3 requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdPwriteName, uint64(fd), uint64(iovs), uint64(iovsCount), 3, uint64(resultNwritten)) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) @@ -1704,7 +1704,7 @@ func Test_fdPwrite_offset(t *testing.T) { require.True(t, ok) requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdWriteName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultNwritten)) - actual, ok = mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok = mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) @@ -1895,7 +1895,7 @@ func Test_fdRead(t *testing.T) { <== (nread=6,errno=ESUCCESS) `, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) } @@ -2238,7 +2238,7 @@ func Test_fdReaddir(t *testing.T) { require.True(t, ok) require.Equal(t, tc.expectedBufused, bufused) - mem, ok := mod.Memory().Read(buf, bufused) + mem, ok := mod.Memory().Read(buf, uint64(bufused)) require.True(t, ok) if tc.expectedMem != nil { @@ -2304,7 +2304,7 @@ func Test_fdReaddir_Rewind(t *testing.T) { func Test_fdReaddir_Errors(t *testing.T) { mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFS(fstest.FS)) defer r.Close(testCtx) - memLen := mod.Memory().Size() + memLen := uint32(mod.Memory().Size()) fsc := mod.(*wasm.ModuleInstance).Sys.FS() preopen := fsc.RootFS() @@ -2621,7 +2621,7 @@ func Test_fdSeek(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdSeekName, uint64(fd), uint64(tc.offset), uint64(tc.whence), uint64(resultNewoffset)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) @@ -2640,7 +2640,7 @@ func Test_fdSeek_Errors(t *testing.T) { require.Zero(t, fsc.RootFS().Mkdir("dir", 0o0777)) dirFD := requireOpenFD(t, mod, "dir") - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) tests := []struct { name string @@ -2778,7 +2778,7 @@ func Test_fdTell(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.FdTellName, uint64(fd), uint64(resultNewoffset)) require.Equal(t, expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) @@ -2791,7 +2791,7 @@ func Test_fdTell_Errors(t *testing.T) { mod, fd, log, r := requireOpenFile(t, t.TempDir(), "test_path", []byte("wazero"), true) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) tests := []struct { name string @@ -2869,7 +2869,7 @@ func Test_fdWrite(t *testing.T) { <== (nwritten=6,errno=ESUCCESS) `, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) @@ -2888,7 +2888,7 @@ func Test_fdWrite_Errors(t *testing.T) { // Setup valid test memory iovsCount := uint32(1) - memSize := mod.Memory().Size() + memSize := uint32(mod.Memory().Size()) tests := []struct { name string @@ -3058,7 +3058,7 @@ func Test_pathCreateDirectory_Errors(t *testing.T) { { name: "out-of-memory reading path", fd: sys.FdPreopen, - path: mod.Memory().Size(), + path: uint32(mod.Memory().Size()), pathLen: 1, expectedErrno: wasip1.ErrnoFault, expectedLog: ` @@ -3070,7 +3070,7 @@ func Test_pathCreateDirectory_Errors(t *testing.T) { name: "out-of-memory reading pathLen", fd: sys.FdPreopen, path: 0, - pathLen: mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is OOM for path + pathLen: uint32(mod.Memory().Size()) + 1, // path is in the valid memory range, but pathLen is OOM for path expectedErrno: wasip1.ErrnoFault, expectedLog: ` ==> wasi_snapshot_preview1.path_create_directory(fd=3,path=OOM(0,65537)) @@ -3126,7 +3126,7 @@ func Test_pathFilestatGet(t *testing.T) { mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFS(fstest.FS)) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) fileFD := requireOpenFD(t, mod, file) @@ -3405,7 +3405,7 @@ func Test_pathFilestatGet(t *testing.T) { requireErrnoResult(t, tc.expectedErrno, mod, wasip1.PathFilestatGetName, uint64(tc.fd), uint64(tc.flags), uint64(1), uint64(tc.pathLen), uint64(tc.resultFilestat)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(tc.expectedMemory))) require.True(t, ok) require.Equal(t, tc.expectedMemory, actual) }) @@ -4078,7 +4078,7 @@ func Test_pathOpen_Errors(t *testing.T) { { name: "out-of-memory reading path", fd: sys.FdPreopen, - path: mod.Memory().Size(), + path: uint32(mod.Memory().Size()), pathLen: uint32(len(file)), expectedErrno: wasip1.ErrnoFault, expectedLog: ` @@ -4090,7 +4090,7 @@ func Test_pathOpen_Errors(t *testing.T) { name: "out-of-memory reading pathLen", fd: sys.FdPreopen, path: 0, - pathLen: mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is OOM for path + pathLen: uint32(mod.Memory().Size()) + 1, // path is in the valid memory range, but pathLen is OOM for path expectedErrno: wasip1.ErrnoFault, expectedLog: ` ==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=OOM(0,65537),oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=) @@ -4163,7 +4163,7 @@ func Test_pathOpen_Errors(t *testing.T) { pathName: dir, path: 0, pathLen: uint32(len(dir)), - resultOpenedFd: mod.Memory().Size(), // path and pathLen correctly point to the right path, but where to write the opened FD is outside memory. + resultOpenedFd: uint32(mod.Memory().Size()), // path and pathLen correctly point to the right path, but where to write the opened FD is outside memory. expectedErrno: wasip1.ErrnoFault, expectedLog: ` ==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=dir,oflags=,fs_rights_base=,fs_rights_inheriting=,fdflags=) @@ -4277,7 +4277,7 @@ func Test_pathReadlink(t *testing.T) { size, ok := mem.ReadUint32Le(resultBufused) require.True(t, ok) - actual, ok := mem.Read(buf, size) + actual, ok := mem.Read(buf, uint64(size)) require.True(t, ok) require.Equal(t, tc.expectedBuf, string(actual)) }) @@ -4416,7 +4416,7 @@ func Test_pathRemoveDirectory_Errors(t *testing.T) { { name: "out-of-memory reading path", fd: sys.FdPreopen, - path: mod.Memory().Size(), + path: uint32(mod.Memory().Size()), pathLen: 1, expectedErrno: wasip1.ErrnoFault, expectedLog: ` @@ -4428,7 +4428,7 @@ func Test_pathRemoveDirectory_Errors(t *testing.T) { name: "out-of-memory reading pathLen", fd: sys.FdPreopen, path: 0, - pathLen: mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is OOM for path + pathLen: uint32(mod.Memory().Size()) + 1, // path is in the valid memory range, but pathLen is OOM for path expectedErrno: wasip1.ErrnoFault, expectedLog: ` ==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=OOM(0,65537)) @@ -4682,7 +4682,7 @@ func Test_pathRename_Errors(t *testing.T) { name: "out-of-memory reading old path", oldFd: sys.FdPreopen, newFd: sys.FdPreopen, - oldPath: mod.Memory().Size(), + oldPath: uint32(mod.Memory().Size()), oldPathLen: 1, expectedErrno: wasip1.ErrnoFault, expectedLog: ` @@ -4697,7 +4697,7 @@ func Test_pathRename_Errors(t *testing.T) { oldPath: 0, oldPathName: "a", oldPathLen: 1, - newPath: mod.Memory().Size(), + newPath: uint32(mod.Memory().Size()), newPathLen: 1, expectedErrno: wasip1.ErrnoFault, expectedLog: ` @@ -4710,7 +4710,7 @@ func Test_pathRename_Errors(t *testing.T) { oldFd: sys.FdPreopen, newFd: sys.FdPreopen, oldPath: 0, - oldPathLen: mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is OOM for path + oldPathLen: uint32(mod.Memory().Size()) + 1, // path is in the valid memory range, but pathLen is OOM for path expectedErrno: wasip1.ErrnoFault, expectedLog: ` ==> wasi_snapshot_preview1.path_rename(fd=3,old_path=OOM(0,65537),new_fd=3,new_path=) @@ -4724,7 +4724,7 @@ func Test_pathRename_Errors(t *testing.T) { oldPathName: file, oldPathLen: uint32(len(file)), newPath: 0, - newPathLen: mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is OOM for path + newPathLen: uint32(mod.Memory().Size()) + 1, // path is in the valid memory range, but pathLen is OOM for path expectedErrno: wasip1.ErrnoFault, expectedLog: ` ==> wasi_snapshot_preview1.path_rename(fd=3,old_path=file,new_fd=3,new_path=OOM(0,65537)) @@ -4853,7 +4853,7 @@ func Test_pathUnlinkFile_Errors(t *testing.T) { { name: "out-of-memory reading path", fd: sys.FdPreopen, - path: mod.Memory().Size(), + path: uint32(mod.Memory().Size()), pathLen: 1, expectedErrno: wasip1.ErrnoFault, expectedLog: ` @@ -4865,7 +4865,7 @@ func Test_pathUnlinkFile_Errors(t *testing.T) { name: "out-of-memory reading pathLen", fd: sys.FdPreopen, path: 0, - pathLen: mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is OOM for path + pathLen: uint32(mod.Memory().Size()) + 1, // path is in the valid memory range, but pathLen is OOM for path expectedErrno: wasip1.ErrnoFault, expectedLog: ` ==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=OOM(0,65537)) @@ -4990,7 +4990,7 @@ func Test_fdReaddir_dotEntryHasARealInode(t *testing.T) { used, _ := mem.ReadUint32Le(resultBufused) - results, _ := mem.Read(buf, used) + results, _ := mem.Read(buf, uint64(used)) require.Equal(t, dirents, results) } @@ -5059,7 +5059,7 @@ func Test_fdReaddir_opened_file_written(t *testing.T) { used, _ := mem.ReadUint32Le(resultBufused) - results, _ := mem.Read(buf, used) + results, _ := mem.Read(buf, uint64(used)) require.Equal(t, dirents, results) } diff --git a/imports/wasi_snapshot_preview1/poll.go b/imports/wasi_snapshot_preview1/poll.go index d09f30245b..8c8839a5e2 100644 --- a/imports/wasi_snapshot_preview1/poll.go +++ b/imports/wasi_snapshot_preview1/poll.go @@ -62,11 +62,11 @@ func pollOneoffFn(_ context.Context, mod api.Module, params []uint64) sys.Errno mem := mod.Memory() // Ensure capacity prior to the read loop to reduce error handling. - inBuf, ok := mem.Read(in, nsubscriptions*48) + inBuf, ok := mem.Read(in, uint64(nsubscriptions)*48) if !ok { return sys.EFAULT } - outBuf, ok := mem.Read(out, nsubscriptions*32) + outBuf, ok := mem.Read(out, uint64(nsubscriptions)*32) // zero-out all buffer before writing for i := range outBuf { outBuf[i] = 0 diff --git a/imports/wasi_snapshot_preview1/poll_test.go b/imports/wasi_snapshot_preview1/poll_test.go index a5357e7966..d2735c3553 100644 --- a/imports/wasi_snapshot_preview1/poll_test.go +++ b/imports/wasi_snapshot_preview1/poll_test.go @@ -55,7 +55,7 @@ func Test_pollOneoff(t *testing.T) { <== (nevents=1,errno=ESUCCESS) `, "\n"+log.String()) - outMem, ok := mod.Memory().Read(out, uint32(len(expectedMem))) + outMem, ok := mod.Memory().Read(out, uint64(len(expectedMem))) require.True(t, ok) require.Equal(t, expectedMem, outMem) @@ -136,7 +136,7 @@ func Test_pollOneoff_Errors(t *testing.T) { uint64(tc.nsubscriptions), uint64(tc.resultNevents)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - out, ok := mod.Memory().Read(tc.out, uint32(len(tc.expectedMem))) + out, ok := mod.Memory().Read(tc.out, uint64(len(tc.expectedMem))) require.True(t, ok) require.Equal(t, tc.expectedMem, out) @@ -428,7 +428,7 @@ func Test_pollOneoff_Stdin(t *testing.T) { uint64(tc.nsubscriptions), uint64(tc.resultNevents)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - out, ok := mod.Memory().Read(tc.out, uint32(len(tc.expectedMem))) + out, ok := mod.Memory().Read(tc.out, uint64(len(tc.expectedMem))) require.True(t, ok) require.Equal(t, tc.expectedMem, out) @@ -492,7 +492,7 @@ func Test_pollOneoff_Zero(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.PollOneoffName, uint64(0), uint64(out), uint64(nsubscriptions), uint64(resultNevents)) - outMem, ok := mod.Memory().Read(out, uint32(len(expectedMem))) + outMem, ok := mod.Memory().Read(out, uint64(len(expectedMem))) require.True(t, ok) require.Equal(t, expectedMem, outMem) @@ -529,7 +529,7 @@ func Test_pollOneoff_Zero(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.PollOneoffName, uint64(0), uint64(out), uint64(nsubscriptions), uint64(resultNevents)) - outMem, ok = mod.Memory().Read(out, uint32(len(expectedMem))) + outMem, ok = mod.Memory().Read(out, uint64(len(expectedMem))) require.True(t, ok) require.Equal(t, expectedMem, outMem) diff --git a/imports/wasi_snapshot_preview1/random.go b/imports/wasi_snapshot_preview1/random.go index e4d7ccee15..5c86968dd8 100644 --- a/imports/wasi_snapshot_preview1/random.go +++ b/imports/wasi_snapshot_preview1/random.go @@ -41,7 +41,7 @@ func randomGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { randSource := sysCtx.RandSource() buf, bufLen := uint32(params[0]), uint32(params[1]) - randomBytes, ok := mod.Memory().Read(buf, bufLen) + randomBytes, ok := mod.Memory().Read(buf, uint64(bufLen)) if !ok { // out-of-range return sys.EFAULT } diff --git a/imports/wasi_snapshot_preview1/random_test.go b/imports/wasi_snapshot_preview1/random_test.go index 46170a945d..d4364d607d 100644 --- a/imports/wasi_snapshot_preview1/random_test.go +++ b/imports/wasi_snapshot_preview1/random_test.go @@ -22,13 +22,13 @@ func Test_randomGet(t *testing.T) { '?', // stopped after encoding } - length := uint32(5) // arbitrary length, - offset := uint32(1) // offset, + length := uint64(5) // arbitrary length, + offset := uint64(1) // offset, maskMemory(t, mod, len(expectedMemory)) // Invoke randomGet and check the memory side effects! - requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.RandomGetName, uint64(offset), uint64(length)) + requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.RandomGetName, offset, length) require.Equal(t, ` ==> wasi_snapshot_preview1.random_get(buf=1,buf_len=5) <== errno=ESUCCESS @@ -43,7 +43,7 @@ func Test_randomGet_Errors(t *testing.T) { mod, r, log := requireProxyModule(t, wazero.NewModuleConfig()) defer r.Close(testCtx) - memorySize := mod.Memory().Size() + memorySize := uint32(mod.Memory().Size()) tests := []struct { name string diff --git a/imports/wasi_snapshot_preview1/sock.go b/imports/wasi_snapshot_preview1/sock.go index 756c0d3913..291da486d1 100644 --- a/imports/wasi_snapshot_preview1/sock.go +++ b/imports/wasi_snapshot_preview1/sock.go @@ -85,7 +85,7 @@ func sockRecvFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { if !ok { return sys.EINVAL } - firstIovecBuf, ok := mem.Read(firstIovecBufAddr, firstIovecBufLen) + firstIovecBuf, ok := mem.Read(firstIovecBufAddr, uint64(firstIovecBufLen)) if !ok { return sys.EINVAL } diff --git a/imports/wasi_snapshot_preview1/sock_test.go b/imports/wasi_snapshot_preview1/sock_test.go index 2bafbd374d..b1d39183ee 100644 --- a/imports/wasi_snapshot_preview1/sock_test.go +++ b/imports/wasi_snapshot_preview1/sock_test.go @@ -275,7 +275,7 @@ func Test_sockRecv(t *testing.T) { requireErrnoResult(t, tc.expectedErrno, mod, wasip1.SockRecvName, uint64(connFd), uint64(iovs), tc.iovsCount, uint64(tc.flags), uint64(resultRoDatalen), uint64(resultRoDatalen+4)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) @@ -352,7 +352,7 @@ func Test_sockSend(t *testing.T) { requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.SockSendName, uint64(connFd), uint64(iovs), uint64(iovsCount), 0, uint64(resultSoDatalen)) require.Equal(t, tc.expectedLog, "\n"+log.String()) - actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) + actual, ok := mod.Memory().Read(0, uint64(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) diff --git a/imports/wasi_snapshot_preview1/wasi.go b/imports/wasi_snapshot_preview1/wasi.go index 4ef41d501c..564ddf4cc1 100644 --- a/imports/wasi_snapshot_preview1/wasi.go +++ b/imports/wasi_snapshot_preview1/wasi.go @@ -233,12 +233,12 @@ func writeOffsetsAndNullTerminatedValues(mem api.Memory, values [][]byte, offset // The caller may not place bytes directly after offsets, so we have to // read them independently. valuesLen := len(values) - offsetsLen := uint32(valuesLen * 4) // uint32Le + offsetsLen := uint64(valuesLen) * 4 offsetsBuf, ok := mem.Read(offsets, offsetsLen) if !ok { return sys.EFAULT } - bytesBuf, ok := mem.Read(bytes, bytesLen) + bytesBuf, ok := mem.Read(bytes, uint64(bytesLen)) if !ok { return sys.EFAULT } diff --git a/internal/engine/compiler/engine_test.go b/internal/engine/compiler/engine_test.go index c68a05865f..7cc3feb107 100644 --- a/internal/engine/compiler/engine_test.go +++ b/internal/engine/compiler/engine_test.go @@ -135,6 +135,7 @@ func TestCompiler_SliceAllocatedOnHeap(t *testing.T) { hostModuleName, []string{hostFnName}, map[string]*wasm.HostFunc{hostFnName: {ExportName: hostFnName, Code: wasm.Code{GoFunc: hostFn}}}, + map[string]*wasm.Memory{}, enabledFeatures, ) require.NoError(t, err) diff --git a/internal/engine/interpreter/interpreter.go b/internal/engine/interpreter/interpreter.go index caecfee38f..f9368be9aa 100644 --- a/internal/engine/interpreter/interpreter.go +++ b/internal/engine/interpreter/interpreter.go @@ -4024,7 +4024,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, m *wasm.ModuleInstance panic(wasmruntime.ErrRuntimeUnalignedAtomic) } // Just a bounds check - if offset >= memoryInst.Size() { + if int(offset) >= len(memoryInst.Buffer) { panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) } res := memoryInst.Notify(offset, uint32(count)) diff --git a/internal/engine/wazevo/e2e_test.go b/internal/engine/wazevo/e2e_test.go index 6536f9159d..7d2f7b64ae 100644 --- a/internal/engine/wazevo/e2e_test.go +++ b/internal/engine/wazevo/e2e_test.go @@ -1024,7 +1024,7 @@ func TestE2E_stores(t *testing.T) { f := inst.ExportedFunction(testcases.ExportedFunctionName) - mem, ok := inst.Memory().Read(0, wasm.MemoryPageSize) + mem, ok := inst.Memory().Read(0, uint64(wasm.MemoryPageSize)) require.True(t, ok) for _, tc := range []struct { i32 uint32 @@ -1119,7 +1119,7 @@ func TestE2E_reexported_memory(t *testing.T) { mem := m1Inst.Memory() require.Equal(t, mem, m3Inst.Memory()) require.Equal(t, mem, m2Inst.Memory()) - require.Equal(t, uint32(11), mem.Size()/65536) + require.Equal(t, uint64(11), mem.Size()/65536) } func TestStackUnwind_panic_in_host(t *testing.T) { diff --git a/internal/integration_test/engine/adhoc_test.go b/internal/integration_test/engine/adhoc_test.go index 53ca3ead97..694adf22fb 100644 --- a/internal/integration_test/engine/adhoc_test.go +++ b/internal/integration_test/engine/adhoc_test.go @@ -818,7 +818,7 @@ func testMemOps(t *testing.T, r wazero.Runtime) { results, err = sizeFn.Call(testCtx) require.NoError(t, err) require.Equal(t, uint64(1), results[0]) // 1 page - require.Equal(t, uint32(65536), memory.Size()) // 64KB + require.Equal(t, uint64(65536), memory.Size()) // 64KB // Grow again so that the memory size matches memory capacity. results, err = growFn.Call(testCtx, 1) @@ -1055,7 +1055,7 @@ func testCall(t *testing.T, r wazero.Runtime) { // * Wasm code calls wasm.OpcodeMemoryGrowName and this changes the capacity (by default, it will). func testModuleMemory(t *testing.T, r wazero.Runtime) { wasmPhrase := "Well, that'll be the day when you say goodbye." - wasmPhraseSize := uint32(len(wasmPhrase)) + wasmPhraseSize := uint64(len(wasmPhrase)) one := uint32(1) @@ -1109,7 +1109,7 @@ func testModuleMemory(t *testing.T, r wazero.Runtime) { require.Equal(t, wasmPhrase, string(buf)) hostPhrase := "Goodbye, cruel world. I'm off to join the circus." // Intentionally slightly longer. - hostPhraseSize := uint32(len(hostPhrase)) + hostPhraseSize := uint64(len(hostPhrase)) // Copy over the buffer, which should stop at the current length. copy(buf, hostPhrase) diff --git a/internal/integration_test/vs/runtime.go b/internal/integration_test/vs/runtime.go index 2c2a7b4e72..8964ee4bcb 100644 --- a/internal/integration_test/vs/runtime.go +++ b/internal/integration_test/vs/runtime.go @@ -82,7 +82,7 @@ func (m *wazeroModule) Memory() []byte { func (r *wazeroRuntime) log(_ context.Context, mod api.Module, stack []uint64) { offset, byteCount := uint32(stack[0]), uint32(stack[1]) - buf, ok := mod.Memory().Read(offset, byteCount) + buf, ok := mod.Memory().Read(offset, uint64(byteCount)) if !ok { panic("out of memory reading log buffer") } diff --git a/internal/logging/logging.go b/internal/logging/logging.go index ecec61f75c..2e1da2d5fd 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -263,7 +263,7 @@ func writeRef(_ context.Context, _ api.Module, w Writer, i uint32, vals []uint64 func writeMemI32(_ context.Context, mod api.Module, w Writer, i uint32, vals []uint64) { offset := uint32(vals[i]) - byteCount := uint32(4) + byteCount := uint64(4) if v, ok := mod.Memory().ReadUint32Le(offset); ok { w.WriteString(strconv.FormatInt(int64(int32(v)), 10)) //nolint } else { // log the positions that were out of memory @@ -273,7 +273,7 @@ func writeMemI32(_ context.Context, mod api.Module, w Writer, i uint32, vals []u func writeMemH64(_ context.Context, mod api.Module, w Writer, i uint32, vals []uint64) { offset := uint32(vals[i]) - byteCount := uint32(8) + byteCount := uint64(8) if s, ok := mod.Memory().Read(offset, byteCount); ok { hex.NewEncoder(w).Write(s) //nolint } else { // log the positions that were out of memory @@ -283,10 +283,10 @@ func writeMemH64(_ context.Context, mod api.Module, w Writer, i uint32, vals []u func writeString(_ context.Context, mod api.Module, w Writer, i uint32, vals []uint64) { offset, byteCount := uint32(vals[i]), uint32(vals[i+1]) - WriteStringOrOOM(mod.Memory(), w, offset, byteCount) + WriteStringOrOOM(mod.Memory(), w, offset, uint64(byteCount)) } -func WriteStringOrOOM(mem api.Memory, w Writer, offset, byteCount uint32) { +func WriteStringOrOOM(mem api.Memory, w Writer, offset uint32, byteCount uint64) { if s, ok := mem.Read(offset, byteCount); ok { w.Write(s) //nolint } else { // log the positions that were out of memory @@ -294,7 +294,7 @@ func WriteStringOrOOM(mem api.Memory, w Writer, offset, byteCount uint32) { } } -func WriteOOM(w Writer, offset uint32, byteCount uint32) { +func WriteOOM(w Writer, offset uint32, byteCount uint64) { w.WriteString("OOM(") //nolint w.WriteString(strconv.Itoa(int(offset))) //nolint w.WriteByte(',') //nolint diff --git a/internal/wasip1/logging/logging.go b/internal/wasip1/logging/logging.go index d7341a09b4..7881f5e824 100644 --- a/internal/wasip1/logging/logging.go +++ b/internal/wasip1/logging/logging.go @@ -260,7 +260,7 @@ func (i logMemI64) Log(_ context.Context, mod api.Module, w logging.Writer, para type logFilestat uint32 func (i logFilestat) Log(_ context.Context, mod api.Module, w logging.Writer, params []uint64) { - offset, byteCount := uint32(params[i]), uint32(64) + offset, byteCount := uint32(params[i]), uint64(64) if buf, ok := mod.Memory().Read(offset, byteCount); ok { w.WriteString("{filetype=") //nolint w.WriteString(FiletypeName(buf[16])) //nolint @@ -275,7 +275,7 @@ func (i logFilestat) Log(_ context.Context, mod api.Module, w logging.Writer, pa type logFdstat uint32 func (i logFdstat) Log(_ context.Context, mod api.Module, w logging.Writer, params []uint64) { - offset, byteCount := uint32(params[i]), uint32(24) + offset, byteCount := uint32(params[i]), uint64(24) if buf, ok := mod.Memory().Read(offset, byteCount); ok { w.WriteString("{filetype=") //nolint w.WriteString(FiletypeName(buf[0])) //nolint @@ -293,7 +293,7 @@ type logString uint32 func (i logString) Log(_ context.Context, mod api.Module, w logging.Writer, params []uint64) { offset, byteCount := uint32(params[i]), uint32(params[i+1]) - if s, ok := mod.Memory().Read(offset, byteCount); ok { + if s, ok := mod.Memory().Read(offset, uint64(byteCount)); ok { w.Write(s) //nolint } } diff --git a/internal/wasm/binary/decoder.go b/internal/wasm/binary/decoder.go index c4191dae95..c3c129b2df 100644 --- a/internal/wasm/binary/decoder.go +++ b/internal/wasm/binary/decoder.go @@ -35,7 +35,7 @@ func DecodeModule( return nil, ErrInvalidVersion } - memSizer := newMemorySizer(memoryLimitPages, memoryCapacityFromMax) + memSizer := NewMemorySizer(memoryLimitPages, memoryCapacityFromMax) m := &wasm.Module{} var info, line, str, abbrev, ranges []byte // For DWARF Data. @@ -165,11 +165,11 @@ func DecodeModule( } // memorySizer derives min, capacity and max pages from decoded wasm. -type memorySizer func(minPages uint32, maxPages *uint32) (min uint32, capacity uint32, max uint32) +type MemorySizer func(minPages uint32, maxPages *uint32) (min uint32, capacity uint32, max uint32) -// newMemorySizer sets capacity to minPages unless max is defined and +// NewMemorySizer sets capacity to minPages unless max is defined and // memoryCapacityFromMax is true. -func newMemorySizer(memoryLimitPages uint32, memoryCapacityFromMax bool) memorySizer { +func NewMemorySizer(memoryLimitPages uint32, memoryCapacityFromMax bool) MemorySizer { return func(minPages uint32, maxPages *uint32) (min, capacity, max uint32) { if maxPages != nil { if memoryCapacityFromMax { diff --git a/internal/wasm/binary/import.go b/internal/wasm/binary/import.go index 39d310c557..075e2d54ee 100644 --- a/internal/wasm/binary/import.go +++ b/internal/wasm/binary/import.go @@ -12,7 +12,7 @@ import ( func decodeImport( r *bytes.Reader, idx uint32, - memorySizer memorySizer, + memorySizer MemorySizer, memoryLimitPages uint32, enabledFeatures api.CoreFeatures, ret *wasm.Import, diff --git a/internal/wasm/binary/memory_test.go b/internal/wasm/binary/memory_test.go index cb42686476..1b0aa7ff79 100644 --- a/internal/wasm/binary/memory_test.go +++ b/internal/wasm/binary/memory_test.go @@ -110,7 +110,7 @@ func Test_newMemorySizer(t *testing.T) { for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { - sizer := newMemorySizer(tc.limit, tc.memoryCapacityFromMax) + sizer := NewMemorySizer(tc.limit, tc.memoryCapacityFromMax) min, capacity, max := sizer(tc.min, tc.max) require.Equal(t, tc.expectedMin, min) require.Equal(t, tc.expectedCapacity, capacity) @@ -193,7 +193,7 @@ func TestMemoryType(t *testing.T) { if tc.input.IsShared { features = features.SetEnabled(experimental.CoreFeaturesThreads, true) } - binary, err := decodeMemory(bytes.NewReader(b), features, newMemorySizer(tmax, false), tmax) + binary, err := decodeMemory(bytes.NewReader(b), features, NewMemorySizer(tmax, false), tmax) require.NoError(t, err) require.Equal(t, binary, expectedDecoded) }) @@ -248,7 +248,7 @@ func TestDecodeMemoryType_Errors(t *testing.T) { // Allow test to work if threads is ever added to default features by explicitly removing threads features features = features.SetEnabled(experimental.CoreFeaturesThreads, false) } - _, err := decodeMemory(bytes.NewReader(tc.input), features, newMemorySizer(max, false), max) + _, err := decodeMemory(bytes.NewReader(tc.input), features, NewMemorySizer(max, false), max) require.EqualError(t, err, tc.expectedErr) }) } diff --git a/internal/wasm/binary/section.go b/internal/wasm/binary/section.go index 622ee5923e..8c38ca18b9 100644 --- a/internal/wasm/binary/section.go +++ b/internal/wasm/binary/section.go @@ -28,7 +28,7 @@ func decodeTypeSection(enabledFeatures api.CoreFeatures, r *bytes.Reader) ([]was // decodeImportSection decodes the decoded import segments plus the count per wasm.ExternType. func decodeImportSection( r *bytes.Reader, - memorySizer memorySizer, + memorySizer MemorySizer, memoryLimitPages uint32, enabledFeatures api.CoreFeatures, ) (result []wasm.Import, @@ -106,7 +106,7 @@ func decodeTableSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wa func decodeMemorySection( r *bytes.Reader, enabledFeatures api.CoreFeatures, - memorySizer memorySizer, + memorySizer MemorySizer, memoryLimitPages uint32, ) (*wasm.Memory, error) { vs, _, err := leb128.DecodeUint32(r) diff --git a/internal/wasm/binary/section_test.go b/internal/wasm/binary/section_test.go index dcebdbed17..a8a136f1ab 100644 --- a/internal/wasm/binary/section_test.go +++ b/internal/wasm/binary/section_test.go @@ -104,7 +104,7 @@ func TestMemorySection(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - memories, err := decodeMemorySection(bytes.NewReader(tc.input), api.CoreFeaturesV2, newMemorySizer(max, false), max) + memories, err := decodeMemorySection(bytes.NewReader(tc.input), api.CoreFeaturesV2, NewMemorySizer(max, false), max) require.NoError(t, err) require.Equal(t, tc.expected, memories) }) @@ -134,7 +134,7 @@ func TestMemorySection_Errors(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - _, err := decodeMemorySection(bytes.NewReader(tc.input), api.CoreFeaturesV2, newMemorySizer(max, false), max) + _, err := decodeMemorySection(bytes.NewReader(tc.input), api.CoreFeaturesV2, NewMemorySizer(max, false), max) require.EqualError(t, err, tc.expectedErr) }) } diff --git a/internal/wasm/host.go b/internal/wasm/host.go index bca686d1df..87d5ac1bfb 100644 --- a/internal/wasm/host.go +++ b/internal/wasm/host.go @@ -3,6 +3,8 @@ package wasm import ( "errors" "fmt" + "sort" + "strings" "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/internal/wasmdebug" @@ -49,6 +51,7 @@ func NewHostModule( moduleName string, exportNames []string, nameToHostFunc map[string]*HostFunc, + nameToMemory map[string]*Memory, enabledFeatures api.CoreFeatures, ) (m *Module, err error) { if moduleName != "" { @@ -56,13 +59,15 @@ func NewHostModule( } else { return nil, errors.New("a module name must not be empty") } - - if exportCount := uint32(len(nameToHostFunc)); exportCount > 0 { + if exportCount := len(nameToHostFunc) + len(nameToMemory); exportCount > 0 { m.ExportSection = make([]Export, 0, exportCount) m.Exports = make(map[string]*Export, exportCount) if err = addFuncs(m, exportNames, nameToHostFunc, enabledFeatures); err != nil { return } + if err = addMemory(m, nameToMemory); err != nil { + return + } } m.IsHostModule = true @@ -159,6 +164,36 @@ func addFuncs( return nil } +func addMemory(m *Module, nameToMemory map[string]*Memory) error { + memoryCount := uint32(len(nameToMemory)) + + // Only one memory can be defined or imported + if memoryCount > 1 { + memoryNames := make([]string, 0, memoryCount) + for k := range nameToMemory { + memoryNames = append(memoryNames, k) + } + sort.Strings(memoryNames) // For consistent error messages + return fmt.Errorf("only one memory is allowed, but configured: %s", strings.Join(memoryNames, ", ")) + } + + // Find the memory name to export. + var name string + for k, v := range nameToMemory { + name = k + if v.Min > v.Max { + return fmt.Errorf("memory[%s] min %d pages (%s) > max %d pages (%s)", name, v.Min, PagesToUnitOfBytes(v.Min), v.Max, PagesToUnitOfBytes(v.Max)) + } + m.MemorySection = v + } + + if name != "" { + m.ExportSection = append(m.ExportSection, Export{Type: ExternTypeMemory, Name: name, Index: 0}) + m.Exports[name] = &m.ExportSection[len(m.ExportSection)-1] + } + return nil +} + func (m *Module) maybeAddType(params, results []ValueType, enabledFeatures api.CoreFeatures) (Index, error) { if len(results) > 1 { // Guard >1.0 feature multi-value diff --git a/internal/wasm/host_test.go b/internal/wasm/host_test.go index 55c881cd6e..7291c1835d 100644 --- a/internal/wasm/host_test.go +++ b/internal/wasm/host_test.go @@ -23,7 +23,7 @@ func swap(ctx context.Context, x, y uint32) (uint32, uint32) { func TestNewHostModule(t *testing.T) { t.Run("empty name not allowed", func(t *testing.T) { - _, err := NewHostModule("", nil, nil, api.CoreFeaturesV2) + _, err := NewHostModule("", nil, nil, nil, api.CoreFeaturesV2) require.Error(t, err) }) @@ -117,7 +117,7 @@ func TestNewHostModule(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - m, e := NewHostModule(tc.moduleName, tc.exportNames, tc.nameToHostFunc, api.CoreFeaturesV2) + m, e := NewHostModule(tc.moduleName, tc.exportNames, tc.nameToHostFunc, nil, api.CoreFeaturesV2) require.NoError(t, e) requireHostModuleEquals(t, tc.expected, m) require.True(t, m.IsHostModule) @@ -179,7 +179,7 @@ func TestNewHostModule_Errors(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - _, e := NewHostModule(tc.moduleName, tc.exportNames, tc.nameToHostFunc, api.CoreFeaturesV1) + _, e := NewHostModule(tc.moduleName, tc.exportNames, tc.nameToHostFunc, nil, api.CoreFeaturesV1) require.EqualError(t, e, tc.expectedErr) }) } diff --git a/internal/wasm/memory.go b/internal/wasm/memory.go index 1dc276574a..6f256e0f4e 100644 --- a/internal/wasm/memory.go +++ b/internal/wasm/memory.go @@ -130,13 +130,13 @@ func (m *MemoryInstance) Definition() api.MemoryDefinition { } // Size implements the same method as documented on api.Memory. -func (m *MemoryInstance) Size() uint32 { - return m.size() +func (m *MemoryInstance) Size() uint64 { + return uint64(m.size()) } // ReadByte implements the same method as documented on api.Memory. func (m *MemoryInstance) ReadByte(offset uint32) (byte, bool) { - if offset >= m.size() { + if int64(offset) >= int64(m.size()) { return 0, false } return m.Buffer[offset], true @@ -179,16 +179,16 @@ func (m *MemoryInstance) ReadFloat64Le(offset uint32) (float64, bool) { } // Read implements the same method as documented on api.Memory. -func (m *MemoryInstance) Read(offset, byteCount uint32) ([]byte, bool) { - if !m.hasSize(offset, uint64(byteCount)) { +func (m *MemoryInstance) Read(offset uint32, byteCount uint64) ([]byte, bool) { + if !m.hasSize(offset, byteCount) { return nil, false } - return m.Buffer[offset : offset+byteCount : offset+byteCount], true + return m.Buffer[offset : uint64(offset)+byteCount : uint64(offset)+byteCount], true } // WriteByte implements the same method as documented on api.Memory. func (m *MemoryInstance) WriteByte(offset uint32, v byte) bool { - if offset >= m.size() { + if int64(offset) >= m.size() { return false } m.Buffer[offset] = v @@ -309,8 +309,8 @@ func memoryBytesNumToPages(bytesNum uint64) (pages uint32) { } // size returns the size in bytes of the buffer. -func (m *MemoryInstance) size() uint32 { - return uint32(len(m.Buffer)) // We don't lock here because size can't become smaller. +func (m *MemoryInstance) size() int64 { + return int64(len(m.Buffer)) // We don't lock here because size can't become smaller. } // hasSize returns true if Len is sufficient for byteCount at the given offset. diff --git a/internal/wasm/memory_test.go b/internal/wasm/memory_test.go index 167d85becc..c431fe2ab8 100644 --- a/internal/wasm/memory_test.go +++ b/internal/wasm/memory_test.go @@ -161,7 +161,7 @@ func TestMemoryInstance_HasSize(t *testing.T) { tests := []struct { name string - offset uint32 + offset uint64 sizeInBytes uint64 expected bool }{ @@ -207,7 +207,7 @@ func TestMemoryInstance_HasSize(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.expected, memory.hasSize(tc.offset, tc.sizeInBytes)) + require.Equal(t, tc.expected, memory.hasSize(uint32(tc.offset), tc.sizeInBytes)) }) } } @@ -481,7 +481,7 @@ func TestMemoryInstance_WriteUint16Le(t *testing.T) { tests := []struct { name string - offset uint32 + offset uint64 v uint16 expectedOk bool expectedBytes []byte @@ -519,7 +519,7 @@ func TestMemoryInstance_WriteUint16Le(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.expectedOk, memory.WriteUint16Le(tc.offset, tc.v)) + require.Equal(t, tc.expectedOk, memory.WriteUint16Le(uint32(tc.offset), tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+2]) // 2 is the size of uint16 } @@ -532,7 +532,7 @@ func TestMemoryInstance_WriteUint32Le(t *testing.T) { tests := []struct { name string - offset uint32 + offset uint64 v uint32 expectedOk bool expectedBytes []byte @@ -570,7 +570,7 @@ func TestMemoryInstance_WriteUint32Le(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.expectedOk, memory.WriteUint32Le(tc.offset, tc.v)) + require.Equal(t, tc.expectedOk, memory.WriteUint32Le(uint32(tc.offset), tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+4]) // 4 is the size of uint32 } @@ -582,7 +582,7 @@ func TestMemoryInstance_WriteUint64Le(t *testing.T) { memory := &MemoryInstance{Buffer: make([]byte, 100)} tests := []struct { name string - offset uint32 + offset uint64 v uint64 expectedOk bool expectedBytes []byte @@ -620,7 +620,7 @@ func TestMemoryInstance_WriteUint64Le(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.expectedOk, memory.WriteUint64Le(tc.offset, tc.v)) + require.Equal(t, tc.expectedOk, memory.WriteUint64Le(uint32(tc.offset), tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+8]) // 8 is the size of uint64 } @@ -633,7 +633,7 @@ func TestMemoryInstance_WriteFloat32Le(t *testing.T) { tests := []struct { name string - offset uint32 + offset uint64 v float32 expectedOk bool expectedBytes []byte @@ -671,7 +671,7 @@ func TestMemoryInstance_WriteFloat32Le(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.expectedOk, memory.WriteFloat32Le(tc.offset, tc.v)) + require.Equal(t, tc.expectedOk, memory.WriteFloat32Le(uint32(tc.offset), tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+4]) // 4 is the size of float32 } @@ -683,7 +683,7 @@ func TestMemoryInstance_WriteFloat64Le(t *testing.T) { memory := &MemoryInstance{Buffer: make([]byte, 100)} tests := []struct { name string - offset uint32 + offset uint64 v float64 expectedOk bool expectedBytes []byte @@ -721,7 +721,7 @@ func TestMemoryInstance_WriteFloat64Le(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.expectedOk, memory.WriteFloat64Le(tc.offset, tc.v)) + require.Equal(t, tc.expectedOk, memory.WriteFloat64Le(uint32(tc.offset), tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+8]) // 8 is the size of float64 } diff --git a/internal/wasm/store_test.go b/internal/wasm/store_test.go index 41fc4f1718..f5c7cfb11c 100644 --- a/internal/wasm/store_test.go +++ b/internal/wasm/store_test.go @@ -23,7 +23,7 @@ func TestModuleInstance_Memory(t *testing.T) { name string input *Module expected bool - expectedLen uint32 + expectedLen uint64 }{ { name: "no memory", @@ -100,6 +100,7 @@ func TestStore_Instantiate(t *testing.T) { "foo", []string{"fn"}, map[string]*HostFunc{"fn": {ExportName: "fn", Code: Code{GoFunc: func() {}}}}, + nil, api.CoreFeaturesV1, ) require.NoError(t, err) @@ -184,6 +185,7 @@ func TestStore_hammer(t *testing.T) { importedModuleName, []string{"fn"}, map[string]*HostFunc{"fn": {ExportName: "fn", Code: Code{GoFunc: func() {}}}}, + nil, api.CoreFeaturesV1, ) require.NoError(t, err) @@ -243,6 +245,7 @@ func TestStore_hammer_close(t *testing.T) { importedModuleName, []string{"fn"}, map[string]*HostFunc{"fn": {ExportName: "fn", Code: Code{GoFunc: func() {}}}}, + nil, api.CoreFeaturesV1, ) require.NoError(t, err) @@ -307,6 +310,7 @@ func TestStore_Instantiate_Errors(t *testing.T) { importedModuleName, []string{"fn"}, map[string]*HostFunc{"fn": {ExportName: "fn", Code: Code{GoFunc: func() {}}}}, + nil, api.CoreFeaturesV1, ) require.NoError(t, err) diff --git a/runtime_test.go b/runtime_test.go index b7fce3891f..0d7982befd 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -192,7 +192,7 @@ func TestModule_Memory(t *testing.T) { name string wasm []byte expected bool - expectedLen uint32 + expectedLen uint64 }{ { name: "no memory", @@ -226,7 +226,7 @@ func TestModule_Memory(t *testing.T) { defs := module.ExportedMemoryDefinitions() require.Equal(t, 1, len(defs)) def := defs["memory"] - require.Equal(t, tc.expectedLen>>16, def.Min()) + require.Equal(t, tc.expectedLen>>16, uint64(def.Min())) } else { require.Nil(t, mem) require.Zero(t, len(module.ExportedMemoryDefinitions()))