wasmtime-dotnet: Calling function with string arguments returns out of bounds memory error.
Seems like trying to load and call a function that uses pointers to access strings fails to access memory in either an exported or imported memory.
Example code:
using var engine = new Engine();
using var module = Module.FromFile(engine, "../../../wasm/bucketing-lib-debug.wasm");
using var linker = new Linker(engine);
using var store = new Store(engine);
linker.Define(
"env",
"abort",
Function.FromCallback(store, (int message, int filename, int linenum, int colnum) =>
{
var inst = linker.Instantiate(store, module);
var mem = inst.GetMemory(store, "memory");
var messageStr = From64Bitstring(mem.ReadString(store, message, 1000));
var filenameStr = From64Bitstring(mem.ReadString(store, filename, 1000));
var lineNumStr = From64Bitstring(mem.ReadString(store, linenum, 1000));
var colNumStr = From64Bitstring(mem.ReadString(store, colnum, 1000));
Console.WriteLine(messageStr);
Console.WriteLine(filenameStr);
Console.WriteLine(lineNumStr);
Console.WriteLine(colNumStr);
})
);
var memory = new Memory(store, 10);
linker.Define("env", "memory", memory);
var config = "{\"project\":{\"_id\":\"_project\"},\"environment\":{\"_id\":\"environment\"}}\0";
var user = "{\"user_id\":\"test_id\"}";
var configaddr = 0;
var configBytesWritten = memory?.WriteString(store, configaddr, config);
var useraddr = configaddr + configBytesWritten!;
var userBytesWritten = memory?.WriteString(store, (int) useraddr, user);
var instance = linker.Instantiate(store, module);
//var memory = instance.GetMemory(store, "memory");
dynamic generateBucketedConfig = instance.GetFunction(store, "generateBucketedConfig")!;
if (configBytesWritten == null || userBytesWritten == null)
{
Console.Out.WriteLine("Failed to write to memory.");
return;
}
var config2 = memory.ReadString(store, configaddr, (int) configBytesWritten);
var user2 = memory.ReadString(store, (int) useraddr, (int) userBytesWritten);
Console.Out.WriteLine("Config data: " + config2);
Console.Out.WriteLine("user data: " + user2);
var span = memory.GetSpan(store);
var result = generateBucketedConfig?.Invoke(store, (int)configaddr, (int)useraddr);
Console.WriteLine("generateBucketedConfig result: " + result);
WAT file of relevant function showing param usage via pointers:
(func $src/index/generateBucketedConfig (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
global.get $~lib/memory/__stack_pointer
i32.const 12
i32.sub
global.set $~lib/memory/__stack_pointer
call $~stack_check
global.get $~lib/memory/__stack_pointer
i64.const 0
i64.store
global.get $~lib/memory/__stack_pointer
i32.const 0
i32.store offset=8
global.get $~lib/memory/__stack_pointer
global.get $~lib/memory/__stack_pointer
local.get $0
local.set $2
local.get $2
call $~lib/assemblyscript-json/JSON/_JSON.parse<~lib/string/String>
local.tee $2
i32.store
local.get $2
i32.const 3
call $~lib/rt/__instanceof
if (result i32)
local.get $2
else
i32.const 1184
i32.const 2960
i32.const 4
i32.const 41
call $~lib/builtins/abort
unreachable
end
local.tee $2
i32.store
global.get $~lib/memory/__stack_pointer
global.get $~lib/memory/__stack_pointer
local.get $1
local.set $3
local.get $3
call $~lib/assemblyscript-json/JSON/_JSON.parse<~lib/string/String>
local.tee $3
i32.store offset=4
local.get $3
i32.const 3
call $~lib/rt/__instanceof
if (result i32)
local.get $3
else
i32.const 1184
i32.const 2960
i32.const 5
i32.const 39
call $~lib/builtins/abort
unreachable
end
local.tee $3
i32.store offset=4
global.get $~lib/memory/__stack_pointer
i32.const 0
local.get $2
call $src/index/BucketedUserConfig#constructor
local.tee $4
i32.store offset=8
local.get $4
call $src/index/BucketedUserConfig#stringify
local.set $5
global.get $~lib/memory/__stack_pointer
i32.const 12
i32.add
global.set $~lib/memory/__stack_pointer
local.get $5
)
Error output:
Config data: {"project":{"_id":"_project"},"environment":{"_id":"environment"}}
user data: {"user_id":"test_id"}
Unhandled exception. Wasmtime.TrapException: wasm trap: out of bounds memory access
wasm backtrace:
0: 0x36a - <unknown>!~lib/string/String.UTF8.byteLength
1: 0x69f2 - <unknown>!~lib/string/String.UTF8.encode
2: 0x1638 - <unknown>!~lib/string/String.UTF8.encode@varargs
3: 0x6c0e - <unknown>!~lib/assemblyscript-json/util/index/Buffer.fromString
4: 0x5f16 - <unknown>!~lib/assemblyscript-json/JSON/_JSON.parse<~lib/string/String>
5: 0x7c4b - <unknown>!src/index/generateBucketedConfig
6: 0x7f2d - <unknown>!export:src/index/generateBucketedConfig
at Wasmtime.Function.Invoke(StoreContext context, ReadOnlySpan`1 arguments)
at Wasmtime.Function.Invoke(IStore store, Object[] arguments)
at System.Dynamic.UpdateDelegates.UpdateAndExecute4[T0,T1,T2,T3,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
at Example.Program.runWASM() in /Users/jamiesinn/git/dotnet-server-sdk/Example/Program.cs:line 75
at Example.Program.Main(String[] args) in /Users/jamiesinn/git/dotnet-server-sdk/Example/Program.cs:line 12
at Example.Program.<Main>(String[] args)
What are we doing wrong here? or is this an unsupported method of accessing a function?
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 15 (9 by maintainers)
Awesome! Thanks!
We had issues enabling and finding the proper WASI config - it would always complain with not being able to find
fd_write.WASM is a new area for us - and this helps a ton in understanding how to use it!