-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
RuntimeException with out of bounds memory access. #11208
Comments
I haven't been able to reproduce a minimal test case from your examples. Do you have a cut-down test case that compiles and reproduces the problem? Or alternately can you provide the .js+.wasm output built with Disassembling the affected function with |
@Brion Yup! I've prepared a branch for you, and that's how to reproduce the bug:
The error will look like this:
To check the fix you should open
You should see how decoded video frames are stored as PNGs in Also, I've included all the demangling/profiling/tracing into the build, but in case you need something extra, feel free to edit the CMake file. Please let me know in case of any progress. |
Perfect! I'll take a look and see if I can find anything clear. |
@Brion Yeah, I assume it either checks whether the offset is negative and throws or reinterprets the value as unsigned one, goes too far and throws. |
@Brion Thanks! |
Ok, here's the failing bit in the disassembly at
The inner Memory loads fail (at least in node) when the base value is less than 0, which can be easily confirmed in a standalone Wasm module looking like this: (module
(export "setter" $setter)
(export "positive_pointer" $positive_pointer)
(export "negative_pointer" $negative_pointer)
(memory 1)
(func $setter (param i32)
(i32.store8
(i32.const 1)
(local.get $0)
)
)
(func $negative_pointer (result i32)
(return
(i32.load8_s offset=2
(i32.const -1)
)
)
)
(func $positive_pointer (result i32)
(return
(i32.load8_s offset=1
(i32.const 0)
)
)
)
) let fs = require('fs');
let buf = fs.readFileSync('small.wasm');
WebAssembly.instantiate(buf)
.then(({module, instance}) => {
instance.exports.setter(42);
console.log('This will work:');
console.log(instance.exports.positive_pointer());
console.log('This will fail:');
console.log(instance.exports.negative_pointer());
}); I am not certain if this is correct behavior for the Wasm virtual machine; the spec says:
Since all bytes of the effective address are in range, I don't think it should throw, and the code generation seems to assume it's safe to do this technique. Can anyone more familiar with the spec give some insight as to whether this is expected behavior per the spec (in which case codegen may need to change) or if it's a problem with the V8 implementation? I'm not familiar enough with the VM implementation to know if the way offsets are mapped to low-level instructions is causing this behavior as an unintended side effect or anything... |
Is Then this should trap, as that Next I'd check if this is a bug in llvm or binaryen. If you compile with |
@kripken ahhhhhhhhhh, it's interpreted as an unsigned value with no wrapping. Ok that explains why it fails. Yeah definitely a codegen problem, will see if can narrow it down a little. |
@kripken ok with building with (local.set $57
(i32.load8_u offset=14440
(local.get $56)
)
) which does the same thing and fails the same way when run. So I suspect something in the LLVM side is assuming that pointers and load/store offsets wrap when they add together, and needs to be fixed so it doesn't make incorrect optimizations. I can attempt to narrow down a minimal C/C++ test case if that'll help in identifying the problem. :) |
EDIT: Nope. My Emscripten is a year out of date. Still watching this thread out of curiosity. |
Sorry for the late response @Brion - I missed your comment earlier. This doesn't sound like a known issue. Load/store offsets should be heavily tested, and we don't have any other bug reports that sound similar. So this is worrying - getting a reduced testcase would be very helpful! (I suspect you may need to start from the failing code and reduce from there, as I'm guessing writing a new testcase from scratch won't be easy, as nothing else has hit this bug in our testing and fuzzing.) |
This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 30 days. Feel free to re-open at any time if this issue is still relevant. |
Currently, for getting familiar with emscripten and its capabilities, I'm trying to implement some stuff related to video decoding using
FFmpeg
. My code crashes under-O2
setup, because of a raisedRuntimeException
. Interestingly, it works like a charm with no optimizations enabled (-O0
).I've managed to find a workaround, and it appeared that the compiler overthinks. Code:
The problem seems to be critical since the behavior is completely valid from the C++ side.
My current setup:
These issues may be related:
Please let me know if there is anything else I can help with.
The text was updated successfully, but these errors were encountered: