]>
Commit | Line | Data |
---|---|---|
ac3d33df JK |
1 | # Fuzzing |
2 | ||
3 | libgit2 is currently using [libFuzzer](https://libfuzzer.info) to perform | |
4 | automated fuzz testing. libFuzzer only works with clang. | |
5 | ||
0c9c969a | 6 | ## Prerequisites for building fuzz targets: |
ac3d33df JK |
7 | |
8 | 1. All the prerequisites for [building libgit2](https://github.com/libgit2/libgit2). | |
9 | 2. A recent version of clang. 6.0 is preferred. [pre-build Debian/Ubuntu | |
10 | packages](https://github.com/libgit2/libgit2) | |
11 | ||
12 | ## Build | |
13 | ||
14 | 1. Create a build directory beneath the libgit2 source directory, and change | |
15 | into it: `mkdir build && cd build` | |
16 | 2. Choose one sanitizers to add. The currently supported sanitizers are | |
17 | [`address`](https://clang.llvm.org/docs/AddressSanitizer.html), | |
18 | [`undefined`](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html), | |
19 | and [`leak`/`address,leak`](https://clang.llvm.org/docs/LeakSanitizer.html). | |
20 | 3. Create the cmake build environment and configure the build with the | |
21 | sanitizer chosen: `CC=/usr/bin/clang-6.0 CFLAGS="-fsanitize=address" cmake | |
22 | -DBUILD_CLAR=OFF -DBUILD_FUZZERS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo ..`. | |
23 | Note that building the fuzzer targets is incompatible with the | |
24 | tests and examples. | |
25 | 4. Build libgit2: `cmake --build .` | |
26 | 5. Exit the cmake build environment: `cd ..` | |
27 | ||
28 | ## Run the fuzz targets | |
29 | ||
0c9c969a | 30 | 1. `ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolize |
ac3d33df | 31 | LSAN_OPTIONS=allocator_may_return_null=1 |
0c9c969a UG |
32 | ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzzers/packfile_fuzzer |
33 | fuzzers/corpora/packfile/` | |
ac3d33df JK |
34 | |
35 | The `LSAN_OPTIONS` and `ASAN_OPTIONS` are there to allow `malloc(3)` to return | |
0c9c969a UG |
36 | `NULL`, which is expected if a huge chunk of memory is allocated. The |
37 | `LLVM_PROFILE_FILE` environment string can also be added to override the path | |
38 | where libFuzzer will write the coverage report. | |
ac3d33df JK |
39 | |
40 | ## Get coverage | |
41 | ||
42 | In order to get coverage information, you need to add the "-fcoverage-mapping" | |
43 | and "-fprofile-instr-generate CFLAGS, and then run the fuzz target with | |
44 | `-runs=0`. That will produce a file called `default.profraw` (this behavior can | |
45 | be overridden by setting the `LLVM_PROFILE_FILE="yourfile.profraw"` environment | |
46 | variable). | |
47 | ||
48 | 1. `llvm-profdata-6.0 merge -sparse default.profraw -o | |
49 | fuzz_packfile_raw.profdata` transforms the data from a sparse representation | |
50 | into a format that can be used by the other tools. | |
51 | 2. `llvm-cov-6.0 report ./build/fuzz/fuzz_packfile_raw | |
52 | -instr-profile=fuzz_packfile_raw.profdata` shows a high-level per-file | |
53 | coverage report. | |
54 | 3. `llvm-cov-6.0 show ./build/fuzz/fuzz_packfile_raw | |
55 | -instr-profile=fuzz_packfile_raw.profdata [source file]` shows a line-by-line | |
56 | coverage analysis of all the codebase (or a single source file). | |
57 | ||
58 | ## Standalone mode | |
59 | ||
60 | In order to ensure that there are no regresions, each fuzzer target can be run | |
61 | in a standalone mode. This can be done by passing `-DUSE_STANDALONE_FUZZERS=ON`. | |
62 | This makes it compatible with gcc. This does not use the fuzzing engine, but | |
63 | just invokes every file in the chosen corpus. | |
64 | ||
65 | In order to get full coverage, though, you might want to also enable one of the | |
66 | sanitizers. You might need a recent version of clang to get full support. | |
67 | ||
68 | ## References | |
69 | ||
70 | * [libFuzzer](https://llvm.org/docs/LibFuzzer.html) documentation. | |
71 | * [Source-based Code | |
72 | Coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html). |