blob: a22e7c5d10083cc8f8e9c722f3612fee8def172d [file] [log] [blame] [view]
aizatsky9c8c5b02016-03-30 22:09:091# Getting Started with libFuzzer in Chrome
aizatskya6f86292016-03-18 00:22:242
3*** note
mmoroz27ea9c22016-04-07 21:17:484**Prerequisites:** libFuzzer in Chrome is supported with GN on Linux only.
aizatskya6f86292016-03-18 00:22:245***
6
7This document will walk you through:
8
9* setting up your build enviroment.
10* creating your first fuzzer.
11* running the fuzzer and verifying its vitals.
12
aizatskya6f86292016-03-18 00:22:2413## Configure Build
14
15Use `use_libfuzzer` GN argument together with sanitizer to generate build files:
16
mmorozdb4e66a12016-11-04 22:14:2417*Notice*: current implementation also supports `use_afl` argument, but it is
18recommended to use libFuzzer for development. Running libFuzzer locally doesn't
19require any special configuration and quickly gives meaningful output for speed,
20coverage and other parameters.
21
aizatskya6f86292016-03-18 00:22:2422```bash
23# With address sanitizer
aizatsky36f509942016-10-13 23:05:1724gn gen out/libfuzzer '--args=use_libfuzzer=true is_asan=true is_debug=false enable_nacl=false' --check
aizatskya6f86292016-03-18 00:22:2425```
26
27Supported sanitizer configurations are:
28
29| GN Argument | Description |
30|--------------|----|
aizatsky8f19edd2016-09-01 20:54:5031| `is_asan=true` | enables [Address Sanitizer] to catch problems like buffer overruns. |
32| `is_msan=true` | enables [Memory Sanitizer] to catch problems like uninitialed reads. |
33| `is_ubsan_security=true` | enables [Undefined Behavior Sanitizer] to catch<sup>\[[1](#Notes)\]</sup> undefined behavior like integer overflow. |
34| | it is possible to run libfuzzer without any sanitizers; *probably not what you want*.|
aizatskya6f86292016-03-18 00:22:2435
36
37## Write Fuzzer Function
38
39Create a new .cc file and define a `LLVMFuzzerTestOneInput` function:
40
41```cpp
reillyg21fe44502016-05-20 22:28:5042#include <stddef.h>
43#include <stdint.h>
44
45extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
aizatskya6f86292016-03-18 00:22:2446 // put your fuzzing code here and use data+size as input.
47 return 0;
48}
49```
50
51[url_parse_fuzzer.cc] is a simple example of real-world fuzzer.
52
53## Define GN Target
54
55Define `fuzzer_test` GN target:
56
aizatsky00a06202016-10-10 21:58:5257```python
aizatskya6f86292016-03-18 00:22:2458import("//testing/libfuzzer/fuzzer_test.gni")
59fuzzer_test("my_fuzzer") {
60 sources = [ "my_fuzzer.cc" ]
61 deps = [ ... ]
62}
63```
64
65## Build and Run Fuzzer Locally
66
67Build with ninja as usual and run:
68
69```bash
70ninja -C out/libfuzzer url_parse_fuzzer
mmoroz27ea9c22016-04-07 21:17:4871./out/libfuzzer/url_parse_fuzzer
aizatskya6f86292016-03-18 00:22:2472```
73
74Your fuzzer should produce output like this:
75
76```
77INFO: Seed: 1787335005
78INFO: -max_len is not provided, using 64
79INFO: PreferSmall: 1
80#0 READ units: 1 exec/s: 0
81#1 INITED cov: 2361 bits: 95 indir: 29 units: 1 exec/s: 0
82#2 NEW cov: 2710 bits: 359 indir: 36 units: 2 exec/s: 0 L: 64 MS: 0
aizatskya6f86292016-03-18 00:22:2483```
84
aizatsky9c8c5b02016-03-30 22:09:0985The `... NEW ...` line appears when libFuzzer finds new and interesting input. The
aizatskya6f86292016-03-18 00:22:2486efficient fuzzer should be able to finds lots of them rather quickly.
aizatsky9b70cf1b2016-03-18 19:33:5087The `... pulse ...` line will appear periodically to show the current status.
aizatskya6f86292016-03-18 00:22:2488
aizatsky00a06202016-10-10 21:58:5289## Improving Your Fuzzer
aizatskya6f86292016-03-18 00:22:2490
aizatsky00a06202016-10-10 21:58:5291Your fuzzer may immediately discover interesting (i.e. crashing) inputs.
92To make it more efficient, several small steps can take you really far:
mmoroz9e075592016-05-06 08:37:5393
aizatsky00a06202016-10-10 21:58:5294* Create seed corpus. Add `seed_corpus = "src/fuzz-testcases/"` attribute
95to your fuzzer targets and add example files in appropriate folder. Read more
96in [Seed Corpus] section of efficient fuzzer guide.
97*Make sure corpus files are appropriately licensed.*
98* Create mutation dictionary. With a `dict = "protocol.dict"` attribute and
99`key=value` dicitionary file format, mutations can be more effective.
100See [Fuzzer Dictionary].
101* Specify maximum testcase length. By default libFuzzer uses `-max_len=64`
102 (or takes the longest testcase in a corpus). ClusterFuzz takes
mmoroz9e075592016-05-06 08:37:53103random value in range from `1` to `10000` for each fuzzing session and passes
104that value to libFuzzers. If corpus contains testcases of size greater than
aizatsky00a06202016-10-10 21:58:52105`max_len`, libFuzzer will use only first `max_len` bytes of such testcases.
106See [Maximum Testcase Length].
mmoroz9e075592016-05-06 08:37:53107
robert.bradford160c5982016-08-30 17:04:30108## Disable noisy error message logging
109
110If the code that you are a fuzzing generates error messages when encountering
111incorrect or invalid data then you need to silence those errors in the fuzzer.
112
113If the target uses the Chromium logging APIs, the best way to do that is to
114override the environment used for logging in your fuzzer:
115
116```cpp
117struct Environment {
118 Environment() {
119 logging::SetMinLogLevel(logging::LOG_FATAL);
120 }
121};
122
123Environment* env = new Environment();
124```
125
aizatskya6f86292016-03-18 00:22:24126## Submitting Fuzzer to ClusterFuzz
127
128ClusterFuzz builds and executes all `fuzzer_test` targets in the source tree.
129The only thing you should do is to submit a fuzzer into Chrome.
130
131## Next Steps
132
133* After your fuzzer is submitted, you should check its [ClusterFuzz status] in
134a day or two.
135* Check the [Efficient Fuzzer Guide] to better understand your fuzzer
136performance and for optimization hints.
137
138
mmoroz5a2604d42016-04-21 10:08:13139## Notes
140[1] By default UBSan doesn't crash once undefined behavior has been detected.
141To make it crash the following additional option should be provided:
142
143```bash
144UBSAN_OPTIONS=halt_on_error=1 ./fuzzer <corpus_directory_or_single_testcase_path>
145```
146
147Other useful options (used by ClusterFuzz) are:
148```bash
149UBSAN_OPTIONS=symbolize=1:halt_on_error=1:print_stacktrace=1 ./fuzzer <corpus_directory_or_single_testcase_path>
150```
151
152
aizatskya6f86292016-03-18 00:22:24153[Address Sanitizer]: http://clang.llvm.org/docs/AddressSanitizer.html
mmoroz9e075592016-05-06 08:37:53154[ClusterFuzz status]: clusterfuzz.md#Status-Links
mmoroz9e075592016-05-06 08:37:53155[Efficient Fuzzer Guide]: efficient_fuzzer.md
aizatsky00a06202016-10-10 21:58:52156[Fuzzer Dictionary]: efficient_fuzzer.md#Fuzzer-Dictionary
mmoroz9e075592016-05-06 08:37:53157[Maximum Testcase Length]: efficient_fuzzer.md#Maximum-Testcase-Length
aizatsky00a06202016-10-10 21:58:52158[Memory Sanitizer]: http://clang.llvm.org/docs/MemorySanitizer.html
159[Seed Corpus]: efficient_fuzzer.md#Seed-Corpus
160[Undefined Behavior Sanitizer]: http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
161[crbug/598448]: https://bugs.chromium.org/p/chromium/issues/detail?id=598448
aizatsky9c8c5b02016-03-30 22:09:09162[url_parse_fuzzer.cc]: https://code.google.com/p/chromium/codesearch#chromium/src/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc