Runtime Error: Out of Bounds Memory Access
Closed this issue · 6 comments
Hello! So at Fastly we're currently debugging some code from a user of Compute@Edge, and we have determined that we found a bug in the AS runtime.
We’re seeing a crash in the collector, and this is the stack trace that we get with ASC_RTRACE=1
:
WebAssembly trapped: wasm trap: out of bounds memory access
wasm backtrace:
0: 0x890 - <unknown>!~lib/rt/itcms/__visit
1: 0xcb8 - <unknown>!~lib/rt/itcms/step
2: 0x1100 - <unknown>!~lib/rt/itcms/__new
3: 0x6fbb - <unknown>!~lib/string/String.UTF8.encode
4: 0x13a6 - <unknown>!~lib/as-wasi/as-wasi/Descriptor#writeString
5: 0x141a - <unknown>!~lib/as-wasi/as-wasi/Console.log
6: 0x5a82 - <unknown>!assembly/[Omitted for privacy, essentially is a logging function 😄 ]
7: 0x5fb5 - <unknown>!assembly/index/main
8: 0x644e - <unknown>!start:assembly/index
9: 0x313e - <unknown>!~start
We're still doing an investigation to nail this down on our end a bit more, and I'll try and look into trying to make a reproducible test case. But! Any tips to help us investigate would be appreciated! Thanks! 😄
cc @dcodeIO @MaxGraey since y'all work on the runtime the most 😄
More context:
rt/itcms/__visit
is reading out of bounds at 0xffffffed
, which means a value of 1
was on the shadow stack given a TOTAL_OVERHEAD
of 20 bytes (i.e. 1
- 20
= 0xffffffed
).
Oddly enough, I found as-wasi/as-wasi/Console.log
(0.4.5) to have the following code:
(func $~lib/as-wasi/as-wasi/Console.log (param $0 i32)
global.get $~lib/memory/__stack_pointer
i32.const 4
i32.sub
global.set $~lib/memory/__stack_pointer
call $~stack_check
global.get $~lib/memory/__stack_pointer
i32.const 0
i32.store
global.get $~lib/memory/__stack_pointer
i32.const 1
i32.store
i32.const 1
local.get $0
call $~lib/as-wasi/as-wasi/Descriptor#writeString
global.get $~lib/memory/__stack_pointer
i32.const 4
i32.add
global.set $~lib/memory/__stack_pointer
)
Note this code specifically that follows a write of 0
to the same address:
global.get $~lib/memory/__stack_pointer
i32.const 1
i32.store
Is that ever correct? I can't seem to find any other places where a non-zero constant is stored on the shadow stack like this.
Signs pointing to a asc bug?
Makes me wonder if this is from as-wasi changetype
ing raw fds to managed Descriptor
objects. That would explain the 1
, in that Stdout(): Descriptor { return new Descriptor(1); };
would be on the shadow stack. If this assumption is correct, changing Descriptor
in as-was to be @unmanaged
could solve this.
That does fix the issue. @torch2424 can you move this issue over to the as-wasi repo for them to properly decorate Descriptor
such that it's not tracked by the GC?
Fwiw, we also have a console
implementation in the standard library now. Let me know if there is something else you'd need that as-wasi supports but our standard library doesn't yet :)
Thank you, can also confirm that using console
from stdlib also solves the issue as it bypasses the problematic code in as-wasi
.
Totally! I can move this over to the as-wasi
repo! Thank you so much for the help here @dcodeIO and @peterhuene ! 😄 Closing this one out 🎉