Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 1 | --- |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 2 | title: 'Fuzzing' |
| 3 | linkTitle: 'Fuzzing' |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 4 | --- |
| 5 | |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 6 | ## Reproducing using `fuzz` |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 7 | |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 8 | We assume that you can [build Skia](/docs/user/build). Many fuzzes only |
| 9 | reproduce when building with ASAN or MSAN; see |
| 10 | [those instructions for more details](../xsan). |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 11 | |
| 12 | When building, you should add the following args to BUILD.gn to make reproducing |
| 13 | less machine- and platform- dependent: |
| 14 | |
| 15 | skia_use_fontconfig=false |
| 16 | skia_use_freetype=true |
| 17 | skia_use_system_freetype2=false |
| 18 | skia_use_wuffs=true |
| 19 | skia_enable_skottie=true |
| 20 | skia_enable_fontmgr_custom_directory=false |
| 21 | skia_enable_fontmgr_custom_embedded=false |
| 22 | skia_enable_fontmgr_custom_empty=true |
| 23 | |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 24 | All that is needed to reproduce a fuzz downloaded from ClusterFuzz or oss-fuzz |
| 25 | is to run something like: |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 26 | |
| 27 | out/ASAN/fuzz -b /path/to/downloaded/testcase |
| 28 | |
| 29 | The fuzz binary will try its best to guess what the type/name should be based on |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 30 | the name of the testcase. Manually providing type and name is also supported, |
| 31 | like: |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 32 | |
| 33 | out/ASAN/fuzz -t filter_fuzz -b /path/to/downloaded/testcase |
| 34 | out/ASAN/fuzz -t api -n RasterN32Canvas -b /path/to/downloaded/testcase |
| 35 | |
| 36 | To enumerate all supported types and names, run the following: |
| 37 | |
| 38 | out/ASAN/fuzz --help # will list all types |
| 39 | out/ASAN/fuzz -t api # will list all names |
| 40 | |
| 41 | If the crash does not show up, try to add the flag --loops: |
| 42 | |
| 43 | out/ASAN/fuzz -b /path/to/downloaded/testcase --loops <times-to-run> |
| 44 | |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 45 | ## Writing fuzzers with libfuzzer |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 46 | |
| 47 | libfuzzer is an easy way to write new fuzzers, and how we run them on oss-fuzz. |
| 48 | Your fuzzer entry point should implement this API: |
| 49 | |
| 50 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t*, size_t); |
| 51 | |
| 52 | First install Clang and libfuzzer, e.g. |
| 53 | |
| 54 | sudo apt install clang-10 libc++-10-dev libfuzzer-10-dev |
| 55 | |
| 56 | You should now be able to use `-fsanitize=fuzzer` with Clang. |
| 57 | |
| 58 | Set up GN args to use libfuzzer: |
| 59 | |
| 60 | cc = "clang-10" |
| 61 | cxx = "clang++-10" |
| 62 | sanitize = "fuzzer" |
Kevin Lubick | 7cece5e | 2021-09-16 14:27:50 -0400 | [diff] [blame] | 63 | extra_cflags = [ "-DSK_BUILD_FOR_LIBFUZZER", # enables fuzzer-constraints (see below) |
| 64 | "-O1" # Or whatever you want. |
| 65 | ] |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 66 | ... |
| 67 | |
| 68 | Build Skia and your fuzzer entry point: |
| 69 | |
| 70 | ninja -C out/libfuzzer skia |
| 71 | clang++-10 -I. -O1 -fsanitize=fuzzer fuzz/oss_fuzz/whatever.cpp out/libfuzzer/libskia.a |
| 72 | |
| 73 | Run your new fuzzer binary |
| 74 | |
| 75 | ./a.out |
| 76 | |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 77 | ## Fuzzing Defines |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 78 | |
Joe Gregorio | e296c56 | 2021-04-05 11:39:40 -0400 | [diff] [blame] | 79 | There are some defines that can help guide a fuzzer to be more productive (e.g. |
| 80 | avoid OOMs, avoid unnecessarily slow code). |
Joe Gregorio | 02f7202 | 2021-03-27 10:12:45 -0400 | [diff] [blame] | 81 | |
| 82 | // Required for fuzzing with afl-fuzz to prevent OOMs from adding noise. |
| 83 | SK_BUILD_FOR_AFL_FUZZ |
| 84 | |
| 85 | // Required for fuzzing with libfuzzer |
| 86 | SK_BUILD_FOR_LIBFUZZER |
| 87 | |
| 88 | // This define adds in guards to abort when we think some code path will take a long time or |
| 89 | // use a lot of RAM. It is set by default when either of the above defines are set. |
| 90 | SK_BUILD_FOR_FUZZER |