]> git.proxmox.com Git - libgit2.git/blob - docs/fuzzing.md
cd825766b73516e5e0e28334723f1af985b136a5
[libgit2.git] / docs / fuzzing.md
1 # Fuzzing
2
3 libgit2 is currently using [libFuzzer](https://libfuzzer.info) to perform
4 automated fuzz testing. libFuzzer only works with clang.
5
6 ## Prerequisites** for building fuzz targets:
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
30 1. `ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolize-6.0
31 LSAN_OPTIONS=allocator_may_return_null=1
32 ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzz/fuzz_packfile_raw
33 fuzz/corpora/fuzz_packfile_raw/`
34
35 The `LSAN_OPTIONS` and `ASAN_OPTIONS` are there to allow `malloc(3)` to return
36 `NULL`. The `LLVM_PROFILE_FILE` is there to override the path where libFuzzer
37 will write the coverage report.
38
39 ## Get coverage
40
41 In order to get coverage information, you need to add the "-fcoverage-mapping"
42 and "-fprofile-instr-generate CFLAGS, and then run the fuzz target with
43 `-runs=0`. That will produce a file called `default.profraw` (this behavior can
44 be overridden by setting the `LLVM_PROFILE_FILE="yourfile.profraw"` environment
45 variable).
46
47 1. `llvm-profdata-6.0 merge -sparse default.profraw -o
48 fuzz_packfile_raw.profdata` transforms the data from a sparse representation
49 into a format that can be used by the other tools.
50 2. `llvm-cov-6.0 report ./build/fuzz/fuzz_packfile_raw
51 -instr-profile=fuzz_packfile_raw.profdata` shows a high-level per-file
52 coverage report.
53 3. `llvm-cov-6.0 show ./build/fuzz/fuzz_packfile_raw
54 -instr-profile=fuzz_packfile_raw.profdata [source file]` shows a line-by-line
55 coverage analysis of all the codebase (or a single source file).
56
57 ## Standalone mode
58
59 In order to ensure that there are no regresions, each fuzzer target can be run
60 in a standalone mode. This can be done by passing `-DUSE_STANDALONE_FUZZERS=ON`.
61 This makes it compatible with gcc. This does not use the fuzzing engine, but
62 just invokes every file in the chosen corpus.
63
64 In order to get full coverage, though, you might want to also enable one of the
65 sanitizers. You might need a recent version of clang to get full support.
66
67 ## References
68
69 * [libFuzzer](https://llvm.org/docs/LibFuzzer.html) documentation.
70 * [Source-based Code
71 Coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html).