-
Notifications
You must be signed in to change notification settings - Fork 67
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
Ability to fuzz wasm-compiled contracts #1103
Comments
https://github.com/rust-fuzz/sancov interoperates with llvms sanitizercoverage/libfuzzer. wasmi can use it to e.g. insert instrumentation on branches. |
I pinged fitzgen about this subject and he said that although he wrote the sancov bindings, he could not actually get them to work. He was trying to dynamically create counters and libfuzzer would not see them. So if we want to try to do this, the starting point will be those sancov bidings, but we're on our own. |
@graydon did successesfully interop with sancov in this project: https://github.com/graydon/photesthesis/blob/main/src/test.cpp So there's some more code to crossreference. Nick said if we get the sancov bindings to do anything useful he'd be happy to take contributions. |
I have done some initial experiments toward making wasm fuzzable with I think it is doable, but the effort is significant. We'll end up doing at least the following:
There are three basic components that collaborate to fuzz LLVM-compiled code: The instrumented code. Emitted by LLVM. This does several things: Libfuzzer. This does probably too many things. Primarily it implements Some sanitizer. The sanitizers all seem to implement common The big problem we are going to run into is that these components So we'll probably have to write a new library that implements the sanitizer Rust fuzzing is usually done with |
The fuzzer also needs to call into the sanitizer to display backtraces. I haven't looked at exactly how it does this, but it's another function we'll need to override to handle wasm frames. Probably quite difficult because it will need help from |
The backtrace printing looks hard indeed, but might not be necessary to implement. The main place backtraces are needed is to show where a failure occurred, and these appear to be printed from a signal handler with no additional context, right before the process is terminated. At the moment, wasm code can't trigger the kind of panic that fails the fuzzer and requires a backtrace to be printed - instead the test harness calls into a contract and interprets what the contract did, then the harness can decide to panic. In the future it might be desirable for certain types of errors produced by contracts to trigger a fuzzer failure - e.g. if a contract does a raw panic without an error code. Then the fuzzer could immediately exit with a backtrace that included wasm frames, which could be more useful than the test harness failing the test after the fact. |
I'm doing prototyping of this project in https://github.com/brson/soroban-wasm-fuzz-test |
What problem does your feature solve?
Fuzz testing currently requires compiling contracts to native code. Wasm code is a black box to the fuzzer and it gets no feedback from it.
For the most part, developers can adapt and use natively compiled contracts. But what if they want to fuzz contracts they don't have the source to? Maybe their contracts call third party contracts that are wasm only.
What would you like to see?
Compiling a program for fuzzing creates undocumented global tables that get frobbed by the instrumented natively-compiled code. wasmi can be modified to also frob these tables in the same way as LLVM does.
I used to have a link rust definitions of these tables, but seem to have lost it. fitzgen can help understand the technical details.
This would be some hacky code and maybe not worth the maintenance burden.
What alternatives are there?
Just don't do it.
The text was updated successfully, but these errors were encountered: