| 1 | This directory contains two utilities for fuzzing Clang: clang-fuzzer and |
| 2 | clang-proto-fuzzer. Both use libFuzzer to generate inputs to clang via |
| 3 | coverage-guided mutation. |
| 4 | |
| 5 | The two utilities differ, however, in how they structure inputs to Clang. |
| 6 | clang-fuzzer makes no attempt to generate valid C++ programs and is therefore |
| 7 | primarily useful for stressing the surface layers of Clang (i.e. lexer, parser). |
| 8 | clang-proto-fuzzer uses a protobuf class to describe a subset of the C++ |
| 9 | language and then uses libprotobuf-mutator to mutate instantiations of that |
| 10 | class, producing valid C++ programs in the process. As a result, |
| 11 | clang-proto-fuzzer is better at stressing deeper layers of Clang and LLVM. |
| 12 | |
| 13 | =================================== |
| 14 | Building clang-fuzzer |
| 15 | =================================== |
| 16 | Within your LLVM build directory, run CMake with the following variable |
| 17 | definitions: |
| 18 | - CMAKE_C_COMPILER=clang |
| 19 | - CMAKE_CXX_COMPILER=clang++ |
| 20 | - LLVM_USE_SANITIZE_COVERAGE=YES |
| 21 | - LLVM_USE_SANITIZER=Address |
| 22 | |
| 23 | Then build the clang-fuzzer target. |
| 24 | |
| 25 | Example: |
| 26 | cd $LLVM_SOURCE_DIR |
| 27 | mkdir build && cd build |
| 28 | cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \ |
| 29 | -DLLVM_USE_SANITIZE_COVERAGE=YES -DLLVM_USE_SANITIZER=Address |
| 30 | ninja clang-fuzzer |
| 31 | |
| 32 | ====================== |
| 33 | Running clang-fuzzer |
| 34 | ====================== |
| 35 | bin/clang-fuzzer CORPUS_DIR |
| 36 | |
| 37 | |
| 38 | ======================================================= |
| 39 | Building clang-proto-fuzzer (Linux-only instructions) |
| 40 | ======================================================= |
| 41 | Install the necessary dependencies: |
| 42 | - binutils // needed for libprotobuf-mutator |
| 43 | - liblzma-dev // needed for libprotobuf-mutator |
| 44 | - libz-dev // needed for libprotobuf-mutator |
| 45 | - docbook2x // needed for libprotobuf-mutator |
| 46 | - Recent version of protobuf [3.3.0 is known to work] |
| 47 | |
| 48 | Within your LLVM build directory, run CMake with the following variable |
| 49 | definitions: |
| 50 | - CMAKE_C_COMPILER=clang |
| 51 | - CMAKE_CXX_COMPILER=clang++ |
| 52 | - LLVM_USE_SANITIZE_COVERAGE=YES |
| 53 | - LLVM_USE_SANITIZER=Address |
| 54 | - CLANG_ENABLE_PROTO_FUZZER=ON |
| 55 | |
| 56 | Then build the clang-proto-fuzzer and clang-proto-to-cxx targets. Optionally, |
| 57 | you may also build clang-fuzzer with this setup. |
| 58 | |
| 59 | Example: |
| 60 | cd $LLVM_SOURCE_DIR |
| 61 | mkdir build && cd build |
| 62 | cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \ |
| 63 | -DLLVM_USE_SANITIZE_COVERAGE=YES -DLLVM_USE_SANITIZER=Address \ |
| 64 | -DCLANG_ENABLE_PROTO_FUZZER=ON |
| 65 | ninja clang-proto-fuzzer clang-proto-to-cxx |
| 66 | |
| 67 | This directory also contains a Dockerfile which sets up all required |
| 68 | dependencies and builds the fuzzers. |
| 69 | |
| 70 | ============================ |
| 71 | Running clang-proto-fuzzer |
| 72 | ============================ |
| 73 | bin/clang-proto-fuzzer CORPUS_DIR |
| 74 | |
| 75 | Arguments can be specified after -ignore_remaining_args=1 to modify the compiler |
| 76 | invocation. For example, the following command line will fuzz LLVM with a |
| 77 | custom optimization level and target triple: |
| 78 | bin/clang-proto-fuzzer CORPUS_DIR -ignore_remaining_args=1 -O3 -triple \ |
| 79 | arm64apple-ios9 |
| 80 | |
| 81 | To translate a clang-proto-fuzzer corpus output to C++: |
| 82 | bin/clang-proto-to-cxx CORPUS_OUTPUT_FILE |
| 83 | |
| 84 | =================== |
| 85 | llvm-proto-fuzzer |
| 86 | =================== |
| 87 | Like, clang-proto-fuzzer, llvm-proto-fuzzer is also a protobuf-mutator based |
| 88 | fuzzer. It receives as input a cxx_loop_proto which it then converts into a |
| 89 | string of valid LLVM IR: a function with either a single loop or two nested |
| 90 | loops. It then creates a new string of IR by running optimization passes over |
| 91 | the original IR. Currently, it only runs a loop-vectorize pass but more passes |
| 92 | can easily be added to the fuzzer. Once there are two versions of the input |
| 93 | function (optimized and not), llvm-proto-fuzzer uses LLVM's JIT Engine to |
| 94 | compile both functions. Lastly, it runs both functions on a suite of inputs and |
| 95 | checks that both functions behave the same on all inputs. In this way, |
| 96 | llvm-proto-fuzzer can find not only compiler crashes, but also miscompiles |
| 97 | originating from LLVM's optimization passes. |
| 98 | |
| 99 | llvm-proto-fuzzer is built very similarly to clang-proto-fuzzer. You can run the |
| 100 | fuzzer with the following command: |
| 101 | bin/clang-llvm-proto-fuzzer CORPUS_DIR |
| 102 | |
| 103 | To translate a cxx_loop_proto file into LLVM IR do: |
| 104 | bin/clang-loop-proto-to-llvm CORPUS_OUTPUT_FILE |
| 105 | To translate a cxx_loop_proto file into C++ do: |
| 106 | bin/clang-loop-proto-to-cxx CORPUS_OUTPUT_FILE |
| 107 | |
| 108 | Note: To get a higher number of executions per second with llvm-proto-fuzzer it |
| 109 | helps to build it without ASan instrumentation and with the -O2 flag. Because |
| 110 | the fuzzer is not only compiling code, but also running it, as the inputs get |
| 111 | large, the time necessary to fuzz one input can get very high. |
| 112 | Example: |
| 113 | cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \ |
| 114 | -DCLANG_ENABLE_PROTO_FUZZER=ON -DLLVM_USE_SANITIZE_COVERAGE=YES \ |
| 115 | -DCMAKE_CXX_FLAGS="-O2" |
| 116 | ninja clang-llvm-proto-fuzzer clang-loop-proto-to-llvm |
| 117 | |