pw_fuzzer: Using OSS-Fuzz#
pw_fuzzer: Better C++ code through easier fuzzing
Core Pigweed is integrated with OSS-Fuzz, a continuous fuzzing infrastructure
for open source software. Fuzzers listed in in pw_test_groups
will
automatically start being run within a day or so of appearing in the git
repository.
Reproducing Bugs Directly#
Bugs produced by OSS-Fuzz can be found in its Monorail instance. These bugs include:
A detailed report, including a symbolized backtrace.
A revision range indicating when the bug has been detected.
A minimized testcase, which is a fuzzer input that can be used to reproduce the bug.
To reproduce a bug:
Build the fuzzers in a local source checkout using one of the pw_fuzzer: Guides.
Download the minimized testcase from the OSS-Fuzz bug.
Run the fuzzer with the testcase as an argument.
For example, if the testcase is saved as ~/Downloads/testcase
and the fuzzer is the same as in the examples above, you could run:
$ ./out/host/obj/pw_fuzzer/toy_fuzzer ~/Downloads/testcase
As noted in OSS-Fuzz’s documentation on timeouts and OOMs, you may want to add a -timeout=25 or -rss_limit_mb=2560 argument to reproduce timeouts or OOMs, respectively.
Using a OSS-Fuzz Docker Instance#
If Pigweed fails to build for OSS-Fuzz, or if a fuzzer only triggers a bug in OSS-Fuzz and not when run directly, you may want to recreate the OSS-Fuzz environment locally using Docker. You can do so using OSS-Fuzz’s documentation on reproducing issues.
In particular, you can recreate the OSS-Fuzz environment using:
$ python infra/helper.py pull_images
$ python infra/helper.py build_image pigweed
$ python infra/helper.py build_fuzzers --sanitizer <address/undefined> pigweed
Using a Local Source Checkout#
When addressing build failures or issues related to specific fuzzers, it is very useful to have an OSS-Fuzz instance use a local source checkout with edits rather than pull from a public repo. Unfortunately, the normal workflow for using a local source checkout does not work for Pigweed. Pigweed provides an embedded development environment along with source code for individual modules, and this environment includes checks that conflict with the way OSS-Fuzz tries to remap and change ownership of the source code.
To work around this, a helper script is provided as part of the pigweed
project on OSS-Fuzz that wraps the usual infra/helper.py
. For commands that
take a local source path, the wrapper instead provides a --local
flag. This
flag will use the PW_ROOT
environment variable to find the source checkout,
and attempt to mount it in the correct location and set specific environment
variables in order to present a working development environment to the OSS-Fuzz
instance. Also, the pigweed
project is implied:
$ python project/pigweed/helper.py build_fuzzers --sanitizer <sanitizer> --local
The sanitizer
value is one of the usual values based to Clang via
-fsanitize=...
, e.g. “address” or “undefined”.
After building with a local source checkout, you can verify an issue previously found by a fuzzer is fixed:
$ python project/pigweed/helper.py reproduce <fuzzer> ~/Downloads/testcase
For libFuzzer-based fuzzers, fuzzer
will be of the form
{module_name}_{fuzzer_name}
, e.g. pw_protobuf_encoder_fuzzer
.
For FuzzTest-based fuzzers, fuzzer
will additionally include the test case
and be of the form {module_name}_{fuzzer_name}@{test_case}
, e.g.
pw_hdlc_decoder_test@Decoder.ProcessNeverCrashes
.
The helper script attempts to restore proper ownership of the source checkout to the current user on completion. This can also be triggered manually using:
$ python project/pigweed/helper.py reset_local