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