• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1---
2layout: default
3title: Setting up a new project
4parent: Getting started
5has_children: true
6nav_order: 2
7permalink: /getting-started/new-project-guide/
8---
9
10# Setting up a new project
11{: .no_toc}
12
13- TOC
14{:toc}
15---
16
17## Prerequisites
18
19Before you can start setting up your new project for fuzzing, you must do the following:
20
21- [Integrate]({{ site.baseurl }}/advanced-topics/ideal-integration/) one or more [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target)
22  with the project you want to fuzz.
23
24  For examples, see
25[boringssl](https://github.com/google/boringssl/tree/master/fuzz) or
26[SQLite](https://www.sqlite.org/src/artifact/ad79e867fb504338) (C/C++),
27[go-fuzz](https://github.com/dvyukov/go-fuzz-corpus/tree/86a5af9d6842f80b205a082538ea28f61bbb8ccb) or
28[syzkaller](https://github.com/google/syzkaller/tree/7c7ded697e6322b0975f061b7e268fe44f585dab/prog/test)
29(Go).
30
31- [Install Docker](https://docs.docker.com/engine/installation)
32  (Googlers can visit [go/installdocker](https://goto.google.com/installdocker)).
33  [Why Docker?]({{ site.baseurl }}/faq/#why-do-you-use-docker)
34
35  If you want to run `docker` without `sudo`, you can
36  [create a docker group](https://docs.docker.com/engine/installation/linux/ubuntulinux/#/create-a-docker-group).
37
38  **Note:** Docker images can consume significant disk space. Run
39  [docker-cleanup](https://gist.github.com/mikea/d23a839cba68778d94e0302e8a2c200f)
40  periodically to garbage-collect unused images.
41
42- (optional) [Install gsutil](https://cloud.google.com/storage/docs/gsutil_install) for local code coverage testing.
43  For Google internal (gLinux) machines, please refer [here](https://cloud.google.com/storage/docs/gsutil_install#deb) instead.
44
45## Creating the file structure
46
47Each OSS-Fuzz project has a subdirectory
48inside the [`projects/`](https://github.com/google/oss-fuzz/tree/master/projects) directory in the [OSS-Fuzz repository](https://github.com/google/oss-fuzz). For example, the [boringssl](https://github.com/google/boringssl)
49project is located in [`projects/boringssl`](https://github.com/google/oss-fuzz/tree/master/projects/boringssl).
50
51Each project directory also contains the following three configuration files:
52
53* [project.yaml](#projectyaml) - provides metadata about the project.
54* [Dockerfile](#dockerfile) - defines the container environment with information
55on dependencies needed to build the project and its [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target).
56* [build.sh](#buildsh) - defines the build script that executes inside the Docker container and
57generates the project build.
58
59You can automatically create a new directory for your project in OSS-Fuzz and
60generate templated versions of the configuration files
61by running the following commands:
62
63```bash
64$ cd /path/to/oss-fuzz
65$ export PROJECT_NAME=<project_name>
66$ export LANGUAGE=<project_language>
67$ python infra/helper.py generate $PROJECT_NAME --language=$LANGUAGE
68```
69
70Once the template configuration files are created, you can modify them to fit your project.
71
72**Note:** We prefer that you keep and maintain [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your own source code repository. If this isn't possible, you can store them inside the OSS-Fuzz project directory you created.
73
74## project.yaml {#projectyaml}
75
76This configuration file stores project metadata. The following attributes are supported:
77
78- [homepage](#homepage)
79- [language](#language)
80- [primary_contact](#primary)
81- [auto_ccs](#auto_ccs)
82- [main_repo](#main_repo)
83- [vendor_ccs](#vendor) (optional)
84- [sanitizers](#sanitizers) (optional)
85- [architectures](#architectures) (optional)
86- [help_url](#help_url) (optional)
87- [builds_per_day](#build_frequency) (optional)
88
89### homepage
90You project's homepage.
91
92### language
93
94Programming language the project is written in. Values you can specify include:
95
96* `c`
97* `c++`
98* [`go`]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/)
99* [`rust`]({{ site.baseurl }}//getting-started/new-project-guide/rust-lang/)
100* [`python`]({{ site.baseurl }}//getting-started/new-project-guide/python-lang/)
101* [`jvm` (Java, Kotlin, Scala and other JVM-based languages)]({{ site.baseurl }}//getting-started/new-project-guide/jvm-lang/)
102* [`swift`]({{ site.baseurl }}//getting-started/new-project-guide/swift/)
103
104### primary_contact, auto_ccs {#primary}
105The primary contact and list of other contacts to be CCed. Each person listed gets access to ClusterFuzz, including crash reports and fuzzer statistics, and are auto-cced on new bugs filed in the OSS-Fuzz
106tracker. If you're a primary or a CC, you'll need to use a [Google account](https://support.google.com/accounts/answer/176347?hl=en) to get full access. ([why?]({{ site.baseurl }}/faq/#why-do-you-require-a-google-account-for-authentication)).
107
108### main_repo {#main_repo}
109Path to source code repository hosting the code, e.g. `https://path/to/main/repo.git`.
110
111### vendor_ccs (optional) {#vendor}
112The list of vendor email addresses that are downstream consumers of the project and want access to
113the bug reports as they are filed.
114
115Any changes to this list must follow these rules:
116- Approved by the project maintainer (e.g. comment on pull request, reply on project mailing list).
117- An organization email address is used.
118
119### sanitizers (optional) {#sanitizers}
120The list of sanitizers to use. If you don't specify a list, `sanitizers` uses a default list of supported
121sanitizers (currently ["address"](https://clang.llvm.org/docs/AddressSanitizer.html) and
122["undefined"](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html)).
123
124[MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html) ("memory") is also supported
125and recommended, but is not enabled by default due to the likelihood of false positives from
126un-instrumented system dependencies.
127If you want to use "memory," please build all libraries your project needs using
128MemorySanitizer.
129This can be done by building them with the compiler flags provided during
130MemorySanitizer builds.
131Then, you can opt in by adding "memory" to your list of sanitizers.
132
133If your project does not build with a particular sanitizer configuration and you need some time to fix
134it, you can use `sanitizers` to override the defaults temporarily. For example, to disable the
135UndefinedBehaviourSanitizer build, just specify all supported sanitizers except "undefined".
136
137If you want to test a particular sanitizer to see what crashes it generates without filing
138them in the issue tracker, you can set an `experimental` flag. For example, if you want to test "memory", set `experimental: True` like this:
139
140```
141sanitizers:
142 - address
143 - memory:
144    experimental: True
145 - undefined
146 ```
147
148Crashes can be accessed on the [ClusterFuzz
149homepage]({{ site.baseurl }}/further-reading/clusterfuzz#web-interface).
150
151`sanitizers` example: [boringssl](https://github.com/google/oss-fuzz/blob/master/projects/boringssl/project.yaml).
152
153### architectures (optional) {#architectures}
154The list of architectures to fuzz on.
155ClusterFuzz supports fuzzing on x86_64 (aka x64) by default.
156Some projects can benefit from i386 fuzzing. OSS-Fuzz will build and run
157AddressSanitizer with libFuzzer on i386 by doing the following:
158
159```yaml
160architectures:
161 - x86_64
162 - i386
163 ```
164
165By fuzzing on i386 you might find bugs that:
166* Only occur in architecture-specific source code (e.g. code that contains i386 assembly).
167* Exist in architecture-independent source code and which only affects i386 users.
168* Exist in architecture-independent source code and which affects users on other 32-bit platforms such as AArch32 (aka 32-bit ARM).
169
170Note that some bugs which affect x86_64 may be discovered on i386 and filed as such.
171On the testcase page of each oss-fuzz issue is a list of other jobs where the crash reproduces, this can let you know if the crash exists on x86_64 as well.
172
173Fuzzing on i386 is not enabled by default because many projects won't build for i386 without some modification to their OSS-Fuzz build process.
174For example, you will need to link against `$LIB_FUZZING_ENGINE` and possibly install i386 dependencies within the x86_64 docker image ([for example](https://github.com/google/oss-fuzz/blob/5b8dcb5d942b3b8bc173b823fb9ddbdca7ec6c99/projects/gdal/build.sh#L18)) to get things working.
175
176### fuzzing_engines (optional) {#fuzzing_engines}
177The list of fuzzing engines to use.
178By default, `libfuzzer`, `afl`, and `honggfuzz` are used. It is recommended to
179use all of them if possible. `libfuzzer` is required by OSS-Fuzz.
180
181### help_url (optional) {#help_url}
182A link to a custom help URL that appears in bug reports instead of the default
183[OSS-Fuzz guide to reproducing crashes]({{ site.baseurl }}/advanced-topics/reproducing/). This can be useful if you assign
184bugs to members of your project unfamiliar with OSS-Fuzz, or if they should follow a different workflow for
185reproducing and fixing bugs than the standard one outlined in the reproducing guide.
186
187`help_url` example: [skia](https://github.com/google/oss-fuzz/blob/master/projects/skia/project.yaml).
188
189### builds_per_day (optional) {#build_frequency}
190The number of times the project should be built per day.
191OSS-Fuzz allows upto 4 builds per day, and builds once per day by default.
192Example:
193```yaml
194builds_per_day: 2
195```
196
197Will build the project twice per day.
198
199## Dockerfile {#dockerfile}
200
201This configuration file defines the Docker image for your project. Your [build.sh](#buildsh) script will be executed in inside the container you define.
202For most projects, the image is simple:
203```docker
204FROM gcr.io/oss-fuzz-base/base-builder       # base image with clang toolchain
205RUN apt-get update && apt-get install -y ... # install required packages to build your project
206RUN git clone <git_url> <checkout_dir>       # checkout all sources needed to build your project
207WORKDIR <checkout_dir>                       # current directory for the build script
208COPY build.sh fuzzer.cc $SRC/                # copy build script and other fuzzer files in src dir
209```
210In the above example, the git clone will check out the source to `$SRC/<checkout_dir>`.
211
212Depending on your project's language, you will use a different base image,
213for instance `FROM gcr.io/oss-fuzz-base/base-builder-go` for golang.
214
215For an example, see
216[expat/Dockerfile](https://github.com/google/oss-fuzz/tree/master/projects/expat/Dockerfile)
217or
218[syzkaller/Dockerfile](https://github.com/google/oss-fuzz/blob/master/projects/syzkaller/Dockerfile).
219
220In the case of a project with multiple languages/toolchains needed,
221you can run installation scripts `install_lang.sh` where lang is the language needed.
222You also need to setup environment variables needed by this toolchain, for example `GOPATH` is needed by golang.
223For an example, see
224[ecc-diff-fuzzer/Dockerfile](https://github.com/google/oss-fuzz/blob/master/projects/ecc-diff-fuzzer/Dockerfile).
225where we use `base-builder-rust`and install golang
226
227## build.sh {#buildsh}
228
229This file defines how to build binaries for [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your project.
230The script is executed within the image built from your [Dockerfile](#Dockerfile).
231
232In general, this script should do the following:
233
234- Build the project using your build system with the correct compiler.
235- Provide compiler flags as [environment variables](#Requirements).
236- Build your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) and link your project's build with libFuzzer.
237
238Resulting binaries should be placed in `$OUT`.
239
240Here's an example from Expat ([source](https://github.com/google/oss-fuzz/blob/master/projects/expat/build.sh)):
241
242```bash
243#!/bin/bash -eu
244
245./buildconf.sh
246# configure scripts usually use correct environment variables.
247./configure
248
249make clean
250make -j$(nproc) all
251
252$CXX $CXXFLAGS -std=c++11 -Ilib/ \
253    $SRC/parse_fuzzer.cc -o $OUT/parse_fuzzer \
254    $LIB_FUZZING_ENGINE .libs/libexpat.a
255
256cp $SRC/*.dict $SRC/*.options $OUT/
257```
258
259If your project is written in Go, check out the [Integrating a Go project]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/) page.
260
261**Note:**
262
2631. Don't assume the fuzzing engine is libFuzzer by default, because we generate builds for libFuzzer, AFL++ and Honggfuzz fuzzing engine configurations. Instead, link the fuzzing engine using $LIB_FUZZING_ENGINE.
2642. Make sure that the binary names for your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) contain only
265alphanumeric characters, underscore(_) or dash(-). Otherwise, they won't run on our infrastructure.
2663. Don't remove source code files. They are needed for code coverage.
267
268### Temporarily disabling code instrumentation during builds
269
270In 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:
271
272
273```
274CFLAGS_SAVE="$CFLAGS"
275CXXFLAGS_SAVE="$CXXFLAGS"
276unset CFLAGS
277unset CXXFLAGS
278export AFL_NOOPT=1
279
280#
281# build commands here that should not result in instrumented code.
282#
283
284export CFLAGS="${CFLAGS_SAVE}"
285export CXXFLAGS="${CXXFLAGS_SAVE}"
286unset AFL_NOOPT
287```
288
289### build.sh script environment
290
291When your build.sh script is executed, the following locations are available within the image:
292
293| Location| Env Variable | Description |
294|---------| ------------ | ----------  |
295| `/out/` | `$OUT`         | Directory to store build artifacts (fuzz targets, dictionaries, options files, seed corpus archives). |
296| `/src/` | `$SRC`         | Directory to checkout source files. |
297| `/work/`| `$WORK`        | Directory to store intermediate files. |
298
299Although the files layout is fixed within a container, environment variables are
300provided so you can write retargetable scripts.
301
302In case your fuzz target uses the [FuzzedDataProvider] class, make sure it is
303included via `#include <fuzzer/FuzzedDataProvider.h>` directive.
304
305[FuzzedDataProvider]: https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
306
307### build.sh requirements {#Requirements}
308
309Only binaries without an extension are accepted as targets. Extensions are reserved for other artifacts, like .dict.
310
311You *must* use the special compiler flags needed to build your project and fuzz targets.
312These flags are provided in the following environment variables:
313
314| Env Variable           | Description
315| -------------          | --------
316| `$CC`, `$CXX`, `$CCC`  | The C and C++ compiler binaries.
317| `$CFLAGS`, `$CXXFLAGS` | C and C++ compiler flags.
318| `$LIB_FUZZING_ENGINE`  | C++ compiler argument to link fuzz target against the prebuilt engine library (e.g. libFuzzer).
319
320You *must* use `$CXX` as a linker, even if your project is written in pure C.
321
322Most well-crafted build scripts will automatically use these variables. If not,
323pass them manually to the build tool.
324
325See the [Provided Environment Variables](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/README.md#provided-environment-variables) section in
326`base-builder` image documentation for more details.
327
328### Static and dynamic linking of libraries
329The `build.sh` should produce fuzzers that are statically linked. This is because the
330fuzzer build environment is different to the fuzzer runtime environment and if your
331project depends on third party libraries then it is likely they will not be present
332in the execution environment. Thus, any shared libraries you may install or compile in
333`build.sh` or `Dockerfile` will not be present in the fuzzer runtime environment. There
334are exceptions to this rule, and for further information on this please see the [fuzzer environment]({{ site.baseurl }}/further-reading/fuzzer-environment/) page.
335
336## Disk space restrictions
337
338Our builders have a disk size of 250GB (this includes space taken up by the OS). Builds must keep peak disk usage below this.
339
340In addition, please keep the size of the build (everything copied to `$OUT`) small (<10GB uncompressed). The build is repeatedly transferred and unzipped during fuzzing and runs on VMs with limited disk space.
341
342## Fuzzer execution environment
343
344For more on the environment that
345your [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.
346
347## Testing locally
348
349You can build your docker image and fuzz targets locally, so you can test them before you push them to the OSS-Fuzz repository.
350
3511. 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):
352
353    ```bash
354    $ cd /path/to/oss-fuzz
355    $ python infra/helper.py build_image $PROJECT_NAME
356    $ python infra/helper.py build_fuzzers --sanitizer <address/memory/undefined> $PROJECT_NAME
357    ```
358
359    The built binaries appear in the `/path/to/oss-fuzz/build/out/$PROJECT_NAME`
360    directory on your machine (and `$OUT` in the container).
361
362    **Note:** You *must* run your fuzz target binaries inside the base-runner docker
363    container to make sure that they work properly.
364
3652. Find failures to fix by running the `check_build` command:
366
367    ```bash
368    $ python infra/helper.py check_build $PROJECT_NAME
369    ```
370
3713. If you want to test changes against a particular fuzz target, run the following command:
372
373    ```bash
374    $ python infra/helper.py run_fuzzer --corpus-dir=<path-to-temp-corpus-dir> $PROJECT_NAME <fuzz_target>
375    ```
376
3774. We recommend taking a look at your code coverage as a test to ensure that
378your fuzz targets get to the code you expect. This would use the corpus
379generated from the previous `run_fuzzer` step in your local corpus directory.
380
381    ```bash
382    $ python infra/helper.py build_fuzzers --sanitizer coverage $PROJECT_NAME
383    $ python infra/helper.py coverage $PROJECT_NAME --fuzz-target=<fuzz_target> --corpus-dir=<path-to-temp-corpus-dir>
384    ```
385
386You may need to run `python infra/helper.py pull_images` to use the latest
387coverage tools. Please refer to
388[code coverage]({{ site.baseurl }}/advanced-topics/code-coverage/) for detailed
389information on code coverage generation.
390
391
392**Note:** Currently, we only support AddressSanitizer (address) and UndefinedBehaviorSanitizer (undefined)
393configurations by default.
394MemorySanitizer is recommended, but needs to be enabled manually since you must build all runtime dependencies with MemorySanitizer.
395<b>Make sure to test each
396of the supported build configurations with the above commands (build_fuzzers -> run_fuzzer -> coverage).</b>
397
398If everything works locally, it should also work on our automated builders and ClusterFuzz. If you check in
399your files and experience failures, review your [dependencies]({{ site.baseurl }}/further-reading/fuzzer-environment/#dependencies).
400
401## Debugging Problems
402
403If you run into problems, our [Debugging page]({{ site.baseurl }}/advanced-topics/debugging/) lists ways to debug your build scripts and
404[fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target).
405
406## Efficient fuzzing
407
408To improve your fuzz target ability to find bugs faster, you should consider the
409following ways:
410
411### Seed Corpus
412
413Most fuzzing engines use evolutionary fuzzing algorithms. Supplying a seed
414corpus consisting of good sample inputs is one of the best ways to improve [fuzz
415target]({{ site.baseurl }}/reference/glossary/#fuzz-target)'s coverage.
416
417To provide a corpus for `my_fuzzer`, put `my_fuzzer_seed_corpus.zip` file next
418to the [fuzz target]({{ site.baseurl }}/reference/glossary/#fuzz-target)'s binary in `$OUT` during the build. Individual files in this
419archive will be used as starting inputs for mutations. The name of each file in the corpus is the sha1 checksum (which you can get using the `sha1sum` or `shasum` command) of its contents. You can store the corpus
420next to source files, generate during build or fetch it using curl or any other
421tool of your choice.
422(example: [boringssl](https://github.com/google/oss-fuzz/blob/master/projects/boringssl/build.sh#L41)).
423
424Seed corpus files will be used for cross-mutations and portions of them might appear
425in bug reports or be used for further security research. It is important that corpus
426has an appropriate and consistent license.
427
428OSS-Fuzz only: See also [Accessing Corpora]({{ site.baseurl }}/advanced-topics/corpora/) for information about getting access to the corpus we are currently using for your fuzz targets.
429
430### Dictionaries
431
432Dictionaries hugely improve fuzzing efficiency for inputs with lots of similar
433sequences of bytes. [libFuzzer documentation](http://libfuzzer.info#dictionaries)
434
435Put your dict file in `$OUT`. If the dict filename is the same as your target
436binary name (i.e. `%fuzz_target%.dict`), it will be automatically used. If the
437name is different (e.g. because it is shared by several targets), specify this
438in .options file:
439
440```
441[libfuzzer]
442dict = dictionary_name.dict
443```
444
445It is common for several [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target)
446to reuse the same dictionary if they are fuzzing very similar inputs.
447(example: [expat](https://github.com/google/oss-fuzz/blob/master/projects/expat/parse_fuzzer.options)).
448
449### Input Size
450
451By default, the fuzzing engine will generate input of any arbitrary length.
452This might be useful to try corner cases that could lead to a
453security vulnerability. However, if large inputs are not necessary to
454increase the coverage of your target API, it is important to add a limit
455here to significantly improve performance.
456
457```cpp
458if (size < kMinInputLength || size > kMaxInputLength)
459  return 0;
460```
461
462## Checking in to the OSS-Fuzz repository
463
464Once you've tested your fuzzing files locally, fork OSS-Fuzz, commit, and push to the fork. Then
465create a pull request with your change. Follow the
466[Forking Project](https://guides.github.com/activities/forking/) guide if you're new to contributing
467via GitHub.
468
469### Copyright headers
470
471Please include copyright headers for all files checked in to oss-fuzz:
472
473```
474# Copyright 2021 Google LLC
475#
476# Licensed under the Apache License, Version 2.0 (the "License");
477# you may not use this file except in compliance with the License.
478# You may obtain a copy of the License at
479#
480#      http://www.apache.org/licenses/LICENSE-2.0
481#
482# Unless required by applicable law or agreed to in writing, software
483# distributed under the License is distributed on an "AS IS" BASIS,
484# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
485# See the License for the specific language governing permissions and
486# limitations under the License.
487#
488################################################################################
489```
490
491**Exception:** If you're porting a fuzz target from Chromium, keep the original Chromium license header.
492
493## Reviewing results
494
495Once your change is merged, your project and fuzz targets should be automatically built and run on
496ClusterFuzz after a short while (&lt; 1 day). If you think there's a problem, you can check your project's [build status](https://oss-fuzz-build-logs.storage.googleapis.com/index.html).
497
498Use the [ClusterFuzz web interface](https://oss-fuzz.com/) to review the following:
499* Crashes generated
500* Code coverage statistics
501* Fuzzer statistics
502* Fuzzer performance analyzer (linked from fuzzer statistics)
503
504**Note:** Your Google Account must be listed in [project.yaml](#projectyaml) for you to have access to the ClusterFuzz web interface.
505
506### Status Badge
507
508![Example
509Badge](https://oss-fuzz-build-logs.storage.googleapis.com/badges/curl.svg)
510
511Once your project has started [building](https://oss-fuzz-build-logs.storage.googleapis.com/index.html), we'd love it if you added our badge in
512your project's README. This allows you to see bugs found by your OSS-Fuzz
513integration at a glance. See
514[brotli](https://github.com/google/brotli#introduction)'s
515README for an example.
516
517Adding it is super easy, just follow this template:
518```markdown
519[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/<project>.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:<project>)
520```
521