Chromium Code Reviews| Index: testing/libfuzzer/getting_started.md |
| diff --git a/testing/libfuzzer/getting_started.md b/testing/libfuzzer/getting_started.md |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8d0b0e648b51c28eb8ff3d3da3e62f9e53003773 |
| --- /dev/null |
| +++ b/testing/libfuzzer/getting_started.md |
| @@ -0,0 +1,119 @@ |
| +# Getting Started with Libfuzzer in Chrome |
| + |
| +*** note |
| +**Prerequisites:** libfuzzer in chrome is supported with GN on Linux only. |
| +*** |
| + |
| +This document will walk you through: |
| + |
| +* setting up your build enviroment |
| +* creating your first fuzzer |
|
inferno
2016/03/17 16:49:37
nit: end lines 9 and 10 with period like line 11.
aizatsky
2016/03/17 23:39:25
Done.
|
| +* running the fuzzer and verifying its vitals. |
| + |
| +## Check Out ToT Clang |
| + |
| +Libfuzzer relies heavily on compile-time instrumentation. Because it is still |
| +under heavy development you need to use tot clang with libfuzzer: |
| + |
| +```bash |
| +# In chrome/src |
| +LLVM_FORCE_HEAD_REVISION=1 ./tools/clang/scripts/update.py --force-local-build --without-android |
| +``` |
| + |
| +To revert this run the same script without specifying `LLVM_FORCE_HEAD_REVISION`. |
| + |
| +## Configure Build |
| + |
| +Use `use_libfuzzer` GN argument together with sanitizer to generate build files: |
| + |
| +```bash |
| +# With address sanitizer |
| +gn gen out/libfuzzer '--args=use_libfuzzer=true is_asan=true enable_nacl=false' --check |
| +``` |
| + |
| +Supported sanitizer configurations are: |
| + |
| +| GN Argument | Description | |
| +|--------------|----| |
| +| is_asan=true | enables [Address Sanitizer] to catch problems like buffer overruns. | |
| +| is_msan=true | enables [Memory Sanitizer] to catch problems like uninitialed reads. | |
| + |
| + |
| +## Write Fuzzer Function |
| + |
| +Create a new .cc file and define a `LLVMFuzzerTestOneInput` function: |
| + |
| +```cpp |
| +extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { |
| + // put your fuzzing code here and use data+size as input. |
| + return 0; |
| +} |
| +``` |
| + |
| +[url_parse_fuzzer.cc] is a simple example of real-world fuzzer. |
| + |
| +## Define GN Target |
| + |
| +Define `fuzzer_test` GN target: |
| + |
| +``` |
| +import("//testing/libfuzzer/fuzzer_test.gni") |
| +fuzzer_test("my_fuzzer") { |
| + sources = [ "my_fuzzer.cc" ] |
| + deps = [ ... ] |
| +} |
| +``` |
| + |
| +## Build and Run Fuzzer Locally |
| + |
| +Build and run with ninja as usual: |
|
mmoroz
2016/03/17 11:58:13
May be "Build with ninja as usual and run"?
aizatsky
2016/03/17 23:39:25
Done.
|
| + |
| +```bash |
| +ninja -C out/libfuzzer url_parse_fuzzer |
| +./out/libfuzzer url_parse_fuzzer |
| +``` |
| + |
| +Your fuzzer should produce output like this: |
| + |
| +``` |
| +INFO: Seed: 1787335005 |
| +INFO: -max_len is not provided, using 64 |
| +INFO: PreferSmall: 1 |
| +#0 READ units: 1 exec/s: 0 |
| +#1 INITED cov: 2361 bits: 95 indir: 29 units: 1 exec/s: 0 |
| +#2 NEW cov: 2710 bits: 359 indir: 36 units: 2 exec/s: 0 L: 64 MS: 0 |
| +#3 NEW cov: 2715 bits: 371 indir: 37 units: 3 exec/s: 0 L: 64 MS: 1 ShuffleBytes- |
| +#5 NEW cov: 2728 bits: 375 indir: 38 units: 4 exec/s: 0 L: 63 MS: 3 ShuffleBytes-ShuffleBytes-EraseByte- |
| +#6 NEW cov: 2729 bits: 384 indir: 38 units: 5 exec/s: 0 L: 10 MS: 4 ShuffleBytes-ShuffleBytes-EraseByte-CrossOver- |
| +#7 NEW cov: 2733 bits: 424 indir: 39 units: 6 exec/s: 0 L: 63 MS: 1 ShuffleBytes- |
| +#8 NEW cov: 2733 bits: 426 indir: 39 units: 7 exec/s: 0 L: 63 MS: 2 ShuffleBytes-ChangeByte- |
| +#11 NEW cov: 2733 bits: 447 indir: 39 units: 8 exec/s: 0 L: 33 MS: 5 ShuffleBytes-ChangeByte-ChangeASCIIInt-ChangeBit-CrossOver- |
| +#12 NEW cov: 2733 bits: 451 indir: 39 units: 9 exec/s: 0 L: 62 MS: 1 CrossOver- |
| +#16 NEW cov: 2733 bits: 454 indir: 39 units: 10 exec/s: 0 L: 61 MS: 5 CrossOver-ChangeBit-ChangeBit-EraseByte-ChangeBit- |
| +#18 NEW cov: 2733 bits: 458 indir: 39 units: 11 exec/s: 0 L: 24 MS: 2 CrossOver-CrossOver- |
| +``` |
| + |
| +The `NEW` line appears when libfuzzer finds new and interesting input. The |
| +efficient fuzzer should be able to finds lots of them rather quickly. |
| + |
| +The 'pulse' line will appear periodicly to show the current status. |
|
mmoroz
2016/03/17 11:58:13
May be "pulse" -> "pulse..."
aizatsky
2016/03/17 23:39:25
Done.
|
| + |
| + |
| +## Submitting Fuzzer to ClusterFuzz |
| + |
| +ClusterFuzz builds and executes all `fuzzer_test` targets in the source tree. |
| +The only thing you should do is to submit a fuzzer into Chrome. |
| + |
| +## Next Steps |
| + |
| +* After your fuzzer is submitted, you should check its [ClusterFuzz status] in |
| +a day or two. |
| +* Check the [Efficient Fuzzer Guide] to better understand your fuzzer |
| +performance and for optimization hints. |
| + |
| + |
| +[Address Sanitizer]: http://clang.llvm.org/docs/AddressSanitizer.html |
| +[Memory Sanitizer]: http://clang.llvm.org/docs/MemorySanitizer.html |
| +[url_parser_fuzzer.cc]: https://code.google.com/p/chromium/codesearch#chromium/src/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc |
| +[ClusterFuzz status]: ./clusterfuzz.md#Fuzzer-Status |
| +[Efficient Fuzzer Guide]: ./efficient_fuzzer.md |