-
Notifications
You must be signed in to change notification settings - Fork 294
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
Preserve locals before entering control flow during compilation #945
Conversation
This implements naive local preservation in order to see if this fixes the problems with ffmpeg.wasm. This is not efficient during compilation, introduces new attack surfaces at compilation and produces inefficient code. After asserting that this indeed fixes the issues without major performance loss the following needs to happen: 1. We need a new data structure for locals on the compilation stack to efficiently cope with the fact that all locals on the stack need to be preserved frequently, not just a single local. 2. We need to find a way to reduce dynamic allocations in FuncTranslator::preserve_locals. 3. We need to merge copies whenever possible. Since preservation register indices are contiguous we should be able to encode fused copy instructions instead of many single copy instructions.
Seems like the fixes applied to the tests as expected.
While coming up with test cases I couldn't find a single one that would have invalid behavior before these changes. This is because with only a loop control flow structure there is no way to skip certain parts without using block or if control flow structures within the loop body. Someone please proof me wrong. Getting rid of as many local preservations is good for performance if not needed.
This is to unify reusable utility buffers of the Wasmi translator.
This is probably not needed but an additional safety guard
This is so that the caller can use its encoded root instruction index for notification of preservation in a future commit.
Relax its allowed copy instructions since this is going to be needed with fused copies of local preservation instructions.
This fixes a bug with RegisterSpanIter going out of bounds when trying to create a register span that starts with the initial preservation register before its index is being defragmented which caused an i16 integer overflow. Note: we could have also altered the implementation of RegisterSpanIter, however, this would have decreased its efficiency eventually which was less desirable.
This removes a potential attack vector with a malicous Wasm file having lots of values on the compilation stack and a series of blocks or ifs that each have to preserve all locals on the compilation stack. In order to further improve the attack vector resistance we also need to preserve locals on the compilation stack in reverse order of their appearance, e.g. as the compilation stack would have popped from. This commit also contains some needed cleanups.
Since this method is only called for small heaps we can get away by using an ArrayVec and linear search instead of using a BTreeMap.
This softens certain non-critical attack vectors on the small stack mode implementation.
Benchmarks performed locally show that performance does NOT significantly regress for both translation and execution with the changes introduced in this PR. |
Unfortunately I cannot run the Wasmi fuzzer due to some weird nightly related issue with some dependencies:
Note that |
I just clarified here that I am going to merge this PR as is and will start with further investigation on the |
To summarize: The fix implemented in this PR was relatively straight forward to implement. The majority of the work in this PR was focused on ensuring quality of the code and to make the new code resist malicious attackers and making it scalable for the new demands. |
This supposedly fixes #934.
This is still in draft due to the following reasons and ToDos:
Test forloop
control flow.loop
control flow structures local preservation is not needed because it is not possible to conditionally skip local manipulation without usingblock
orif
within theloop
body somewhere. Someone please proof me wrong.CopySpanNonOverlapping
andCopyManyNonOverlapping
.block
andif
.len_locals
toProviders
stack to act as a fast bail out condition for the common case when no locals need to be preserved.BTreeMap
inpreserve_all_locals_inplace
with anArrayVec
and linear search. This avoids heap allocations and won't introduce an attack vector sincepreserve_all_locals_inplace
is guaranteed to operate on very small sets of values.copy
instructions resulting from the new codegen introduced in this PR.copy2
orcopy_many
instructions instead of having multiplecopy
instructions for each preserved local.Run the differential fuzzer in order to see if the changes introduced in this PR are actually generally correct.Follow-Up PRs
ffmpeg.wasm
binary.