• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1---
2layout: default
3parent: ClusterFuzzLite
4title: Build Integration
5has_children: true
6nav_order: 2
7permalink: /clusterfuzzlite/build-integration/
8---
9# Build integration
10{: .no_toc}
11
12- TOC
13{:toc}
14---
15
16## Prerequisites
17ClusterFuzzLite supports statically linked
18[libFuzzer targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) on
19Linux.
20
21We re-use the [OSS-Fuzz](https://github.com/google/oss-fuzz) toolchain to make
22building easier. If you are familiar with this, most of the concepts here are
23exactly the same, with one key difference. Rather than checking out the source
24code in the [`Dockerfile`](#dockerfile) using `git clone`, the `Dockerfile`
25copies in the source code directly during `docker build`.
26
27Before you can start setting up your new project for fuzzing, you must do the following:
28- [Integrate]({{ site.baseurl }}/advanced-topics/ideal-integration/) one or more [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target)
29  with the project you want to fuzz. For examples, see TODO.
30- [Install Docker](https://docs.docker.com/engine/installation)
31  [Why Docker?]({{ site.baseurl }}/faq/#why-do-you-use-docker)
32
33  If you want to run `docker` without `sudo`, you can
34  [create a docker group](https://docs.docker.com/engine/installation/linux/ubuntulinux/#/create-a-docker-group).
35
36  **Note:** Docker images can consume significant disk space. Run
37  [docker-cleanup](https://gist.github.com/mikea/d23a839cba68778d94e0302e8a2c200f)
38  periodically to garbage-collect unused images.
39
40- Clone the OSS-Fuzz repo: `git clone https://github.com/google/oss-fuzz.git`
41
42## Generating an empty build integration
43
44Build integrations consist of three configuration files:
45* [./clusterfuzzlite/project.yaml](#projectyaml) - provides metadata about the project.
46* [./clusterfuzzlite/Dockerfile](#dockerfile) - defines the container environment with information
47on dependencies needed to build the project and its [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target).
48* [./clusterfuzzlite/build.sh](#buildsh) - defines the build script that executes inside the Docker container and
49generates the project build.
50
51These must live in the `.clusterfuzzlite` directory in the root of your
52project's source code checkout.
53
54You can generate empty versions of these files with the following command:
55
56```bash
57$ cd /path/to/oss-fuzz
58$ export PATH_TO_PROJECT=<path_to_your_project>
59$ python infra/helper.py generate $PATH_TO_PROJECT --external
60```
61
62Once the configuration files are generated, you should modify them to fit your
63project.
64
65## project.yaml {#projectyaml}
66
67This configuration file stores project metadata. The following attributes are
68supported:
69
70- [language](#language)
71
72### language
73
74Programming language the project is written in. Values you can specify include:
75
76* `c`
77* `c++`
78* [`go`]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/)
79* [`rust`]({{ site.baseurl }}//getting-started/new-project-guide/rust-lang/)
80* [`python`]({{ site.baseurl }}//getting-started/new-project-guide/python-lang/)
81* [`jvm` (Java, Kotlin, Scala and other JVM-based languages)]({{ site.baseurl }}//getting-started/new-project-guide/jvm-lang/)
82
83## Dockerfile {#dockerfile}
84
85This integration file defines the Docker image for your project.
86Your [build.sh](#buildsh) script will be executed in inside the container you
87define.
88For most projects, the image is simple:
89```docker
90FROM gcr.io/oss-fuzz-base/base-builder          # base image with clang toolchain
91RUN apt-get update && apt-get install -y ...    # install required packages to build your project
92COPY . $SRC/<project_name>                      # checkout all sources needed to build your project
93WORKDIR $SRC/<project_name>                     # current directory for the build script
94COPY ./clusterfuzzlite/build.sh fuzzer.cc $SRC/ # copy build script into src dir
95```
96TODO: Provide examples.
97
98## build.sh {#buildsh}
99
100This file defines how to build binaries for [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your project.
101The script is executed within the image built from your [Dockerfile](#Dockerfile).
102
103In general, this script should do the following:
104
105- Build the project using your build system with OSS-Fuzz's compiler.
106- Provide OSS-Fuzz's compiler flags (defined as [environment variables](#Requirements)) to the build system.
107- Build your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target)
108  and link your project's build with `$LIB_FUZZING_ENGINE` (libFuzzer).
109
110Resulting binaries should be placed in `$OUT`.
111
112Here's an example from Expat
113([source](https://github.com/google/oss-fuzz/blob/master/projects/expat/build.sh)):
114
115```bash
116#!/bin/bash -eu
117
118./buildconf.sh
119# configure scripts usually use correct environment variables.
120./configure
121
122make clean
123make -j$(nproc) all
124
125$CXX $CXXFLAGS -std=c++11 -Ilib/ \
126    $SRC/parse_fuzzer.cc -o $OUT/parse_fuzzer \
127    $LIB_FUZZING_ENGINE .libs/libexpat.a
128
129cp $SRC/*.dict $SRC/*.options $OUT/
130```
131
132If your project is written in Go, check out the [Integrating a Go project]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/) page.
133
134**Note:**
1351. Make sure that the binary names for your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) contain only
136alphanumeric characters, underscore(_) or dash(-). Otherwise, they won't run.
1371. Don't remove source code files. They are needed for code coverage.
138
139
140### Temporarily disabling code instrumentation during builds
141
142In some cases, it's not necessary to instrument every 3rd party library or tool that supports the build target. Use the following snippet to build tools or libraries without instrumentation:
143
144```
145CFLAGS_SAVE="$CFLAGS"
146CXXFLAGS_SAVE="$CXXFLAGS"
147unset CFLAGS
148unset CXXFLAGS
149export AFL_NOOPT=1
150
151#
152# build commands here that should not result in instrumented code.
153#
154
155export CFLAGS="${CFLAGS_SAVE}"
156export CXXFLAGS="${CXXFLAGS_SAVE}"
157unset AFL_NOOPT
158```
159TODO: Figure out if we should include this AFL code.
160
161### build.sh script environment
162
163When your build.sh script is executed, the following locations are available within the image:
164
165| Location| Env Variable | Description |
166|---------| ------------ | ----------  |
167| `/out/` | `$OUT`         | Directory to store build artifacts (fuzz targets, dictionaries, options files, seed corpus archives). |
168| `/src/` | `$SRC`         | Directory to checkout source files. |
169| `/work/`| `$WORK`        | Directory to store intermediate files. |
170
171Although the files layout is fixed within a container, environment variables are
172provided so you can write retargetable scripts.
173
174In case your fuzz target uses the [FuzzedDataProvider] class, make sure it is
175included via `#include <fuzzer/FuzzedDataProvider.h>` directive.
176
177[FuzzedDataProvider]: https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
178
179### build.sh requirements {#Requirements}
180
181Only binaries without an extension are accepted as targets. Extensions are reserved for other artifacts, like .dict.
182
183You *must* use the special compiler flags needed to build your project and fuzz targets.
184These flags are provided in the following environment variables:
185
186| Env Variable           | Description
187| -------------          | --------
188| `$CC`, `$CXX`, `$CCC`  | The C and C++ compiler binaries.
189| `$CFLAGS`, `$CXXFLAGS` | C and C++ compiler flags.
190| `$LIB_FUZZING_ENGINE`  | C++ compiler argument to link fuzz target against the prebuilt engine library (e.g. libFuzzer).
191
192You *must* use `$CXX` as a linker, even if your project is written in pure C.
193
194Most well-crafted build scripts will automatically use these variables. If not,
195pass them manually to the build tool.
196
197See the [Provided Environment Variables](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/README.md#provided-environment-variables) section in
198`base-builder` image documentation for more details.
199
200## Fuzzer execution environment
201
202For more on the environment that
203your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) run in, and the assumptions you can make, see the [fuzzer environment]({{ site.baseurl }}/further-reading/fuzzer-environment/) page.
204
205## Testing locally
206
207You can build your docker image and fuzz targets locally, so you can test them
208before running ClusterFuzzLite.
2091. Run the same helper script you used to create your directory structure, this time using it to build your docker image and [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target):
210
211    ```bash
212    $ cd /path/to/oss-fuzz
213    $ python infra/helper.py build_image $PATH_TO_PROJECT --external
214    $ python infra/helper.py build_fuzzers $PATH_TO_PROJECT --sanitizer <address/undefined/coverage> --external
215    ```
216
217    The built binaries appear in the `/path/to/oss-fuzz/build/out/$PROJECT_NAME`
218    directory on your machine (and `$OUT` in the container). Note that
219    `$PROJECT_NAME` is the name of the directory of your project (e.g. if
220    `$PATH_TO_PROJECT` is `/path/to/systemd`, `$PROJECT_NAME` is systemd.
221
222    **Note:** You *must* run your fuzz target binaries inside the base-runner docker
223    container to make sure that they work properly.
224
2252. Find failures to fix by running the `check_build` command:
226
227    ```bash
228    $ python infra/helper.py check_build $PATH_TO_PROJECT --external
229    ```
230
2313. If you want to test changes against a particular fuzz target, run the following command:
232
233    ```bash
234    $ python infra/helper.py run_fuzzer --external --corpus-dir=<path-to-temp-corpus-dir> $PATH_TO_PROJECT <fuzz_target>
235    ```
236
2374. We recommend taking a look at your code coverage as a test to ensure that
238your fuzz targets get to the code you expect. This would use the corpus
239generated from the previous `run_fuzzer` step in your local corpus directory.
240
241    ```bash
242    $ python infra/helper.py build_fuzzers --sanitizer coverage $PATH_TO_PROJECT
243    $ python infra/helper.py coverage $PATH_TO_PROJECT --fuzz-target=<fuzz_target> --corpus-dir=<path-to-temp-corpus-dir> --external
244    ```
245
246You may need to run `python infra/helper.py pull_images` to use the latest
247coverage tools. Please refer to
248[code coverage]({{ site.baseurl }}/advanced-topics/code-coverage/) for detailed
249information on code coverage generation.
250
251**Note:** Currently, ClusterFuzzLite only supports AddressSanitizer (address)
252and UndefinedBehaviorSanitizer (undefined) configurations.
253<b>Make sure to test each
254of the supported build configurations with the above commands (build_fuzzers -> run_fuzzer -> coverage).</b>
255
256If everything works locally, it should also work on ClusterFuzzLite. If you
257check in your files and experience failures, review your [dependencies]({{site.baseurl }}/further-reading/fuzzer-environment/#dependencies).
258
259## Debugging Problems
260
261If you run into problems, the [Debugging page]({{ site.baseurl }}/advanced-topics/debugging/) lists ways to debug your build scripts and
262[fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target).
263
264## Efficient fuzzing
265
266To improve your fuzz target ability to find bugs faster, please read [this section](
267{{ site.baseurl }}/getting-started/new-project-guide/#efficient-fuzzing).
268
269TODO(metzman): We probably want a TOC for lang-specific guides (which we still need to add).
270