-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory corruption in WASI build #774
Comments
Hi, I was able to reduce the crash to the following: let N = [1,2,3];
N[3] = N;
N % 1; It seems to be some issue with arrays that have circular references. $ wazero run --mount . qjs-wasi.wasm repro.js
error instantiating wasm binary: module[] function[_start] failed: wasm error: out of bounds memory access
wasm stack trace:
.js_call_c_function(i32,i64,i64,i32,i32,i32) i64
.JS_CallInternal(i32,i64,i64,i64,i32,i32,i32) i64
.JS_ToPrimitiveFree(i32,i64,i32) i64
.JS_ToStringInternal(i32,i64,i32) i64
.JS_ToStringFree(i32,i64) i64
.string_buffer_concat_value_free(i32,i64) i32
.js_array_join(i32,i64,i32,i32,i32) i64
.js_call_c_function(i32,i64,i64,i32,i32,i32) i64
.JS_CallInternal(i32,i64,i64,i64,i32,i32,i32) i64
.js_array_toString(i32,i64,i32,i32) i64
.js_call_c_function(i32,i64,i64,i32,i32,i32) i64
.JS_CallInternal(i32,i64,i64,i64,i32,i32,i32) i64
.JS_ToPrimitiveFree(i32,i64,i32) i64
.JS_ToStringInternal(i32,i64,i32) i64
.JS_ToStringFree(i32,i64) i64
.string_buffer_concat_value_free(i32,i64) i32
.js_array_join(i32,i64,i32,i32,i32) i64
.js_call_c_function(i32,i64,i64,i32,i32,i32) i64
.JS_CallInternal(i32,i64,i64,i64,i32,i32,i32) i64
.js_array_toString(i32,i64,i32,i32) i64
.js_call_c_function(i32,i64,i64,i32,i32,i32) i64
.JS_CallInternal(i32,i64,i64,i64,i32,i32,i32) i64
.JS_ToPrimitiveFree(i32,i64,i32) i64
.JS_ToStringInternal(i32,i64,i32) i64
.JS_ToStringFree(i32,i64) i64
.string_buffer_concat_value_free(i32,i64) i32
.js_array_join(i32,i64,i32,i32,i32) i64
.js_call_c_function(i32,i64,i64,i32,i32,i32) i64
.JS_CallInternal(i32,i64,i64,i64,i32,i32,i32) i64
.js_array_toString(i32,i64,i32,i32) i64
... maybe followed by omitted frames Note that I'm not sure if this is the sole issue here, since I'm not sure if this explains the memory corruption portion of this. |
The root of the crash seems to stem from the built-in implementation of Adding |
Good find! Yes, stack overflow detection is disabled in WASI, I wonder if there is a way to make it work... |
It seems like there are 2 bugs here I guess, the stack overflow detection in the WASI build and also the |
Doesn't the stack overflow checks work on other platdorms and thus errored properly? |
Yes, but I'd argue |
Gotcha, I'll take a look! |
https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.join - the algorithm is explicitly recursive (step 7c.i) and throwing a stack overflow exception is allowed. What V8 and SM do is maybe a quality-of-implementation enhancement but note how your W.r.t. the lack of stack checks in wasm builds: we could switch to explicit recursion checks ( |
I'm not sure how you're getting that result. let N = [1,2,3];
N[3] = [N,5,6];
N.toString(); results in |
I suppose we could do that - replace cycles with a hole - but the thing I don't like is that arrays are practically never cyclic so now the really uncommon case impacts the performance of the really common case. We'd need to track cycles in a side table but that isn't free; it costs CPU and memory. If you could persuade tc39 to add a test to that effect to test262, we'd be obliged to support it, but otherwise I'm inclined to leave well enough alone. |
Looking through the source, it seems like there are a fews places that circular references are handled already: The If the |
Messing with the Can you quote the text from the ECMA Standard that specifies the required behavior? |
It's not required by the standard as far as I can tell, but it is something implemented by most other engines, to the point where I wouldn't be surprised if there's a decent amount of existing code that unintentionally relies on this behavior. I found this crash running real-life code after all, and I was personally a bit surprised that something as simple as stringifying an array can cause a stack overflow. I can understand wanting to stick to the specifications though, changing unspecified behavior for compatibility with other engines is opening a bit of a can of worms. The It would be nice to find a solution to the WASI stack overflow issue though, since that's a little harder to work around. |
Hi, I seem to have come across some kind of memory-corruption(?) bug while trying to use the WASI build.
This is the script I was running, it is an obfuscated function extracted from the YouTube player JS.
I added a bit of debug code to the middle of the function here:
I originally was trying to run this using wazero, but got the following output:
I thought this might be a bug with wazero, so I attempted using wasmer, but got the same results:
The couple
stri¡�
before it crashes leads me to believe the script is causing some kind of memory corruption in the WASM runtime.Running this script using the native version (seemingly?) works correctly, though I can't guarantee there isn't some kind of subtle memory corruption going on:
The text was updated successfully, but these errors were encountered: