Fuzzing infrastructure for the Solidity compiler. Contains OSS-Fuzz harnesses, fuzzers, and debug runners to debug & reproduce findings.
git clone --recurse-submodules https://github.com/argotorg/solidity-fuzzing.git
cd solidity-fuzzing
# Or if already cloned without submodules:
git submodule update --init --recursiveMake sure to have the following installed:
- gcc / g++ (C++20 support required, i.e. GCC 10+)
- cmake (>= 3.13)
- make
- libboost-dev, libboost-program-options-dev, libboost-filesystem-dev
- linux-perf
- gdb
- protobuf-compiler (protoc)
- ccache
- docker
We'll need a full solidity build along with debug tools (sol_debug_runner,
yul_debug_runner) built with a standard CMake workflow. They link against the
solidity libraries built from the submodule.
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_FLAGS="-fno-omit-frame-pointer" -DCMAKE_C_FLAGS="-fno-omit-frame-pointer" ..
make -j$(nproc)This builds the following debug tools:
sol_debug_runner— reproducessol_proto_ossfuzz_evmone*findingsyul_debug_runner— reproducesyul_proto_ossfuzz_evmone*findings
docker build -t solidity-ossfuzz -f scripts/docker/Dockerfile.ubuntu.clang.ossfuzz .docker run --rm -v "$(pwd)":/src/solidity-fuzzing -ti solidity-ossfuzz \
/src/solidity-fuzzing/scripts/build_ossfuzz.shThis builds all relevant fuzzer targets under build_ossfuzz.
The most important are the libfuzzer-based protobuf targets to be ran standalone:
sol_proto_ossfuzz_*— Solidity differential fuzzersyul_proto_ossfuzz_*— Yul differential fuzzers
./build_ossfuzz/tools/ossfuzz/sol_proto_ossfuzz_evmone corpus_dirCorpuses are currently stored here: https://github.com/msooseth/solidity-fuzzing-corpus
# Reproduce a sol ProtoBuf EVMOne finding:
./build/sol_debug_runner crash.sol
# Reproduce a Yul Protobuf EVMOne finding:
./build/yul_debug_runner crash.yulPlease see here for the list of all the fuzzers and the documentation on how to use the debug tools.
-
Fuzzing binaries must link against libc++ and not libstdc++ This is [because][2] (1) MemorySanitizer (which flags uses of uninitialized memory) depends on libc++; and (2) because libc++ is instrumented (to check for memory and type errors) and libstdc++ not, the former may find more bugs.
-
Linking against libc++ requires us to compile everything solidity depends on from source (and link these against libc++ as well)
-
To reproduce the compiler versions used by upstream oss-fuzz bots, we need to reuse their docker image containing the said compiler versions
-
Some fuzzers depend on libprotobuf, libprotobuf-mutator, libevmone etc. which may not be available locally; even if they were they might not be the right versions