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 | |