• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1---
2layout: default
3title: Continuous Integration
4parent: Getting started
5nav_order: 5
6permalink: /getting-started/continuous-integration/
7---
8
9# Continuous Integration
10
11OSS-Fuzz offers **CIFuzz**, a GitHub action/CI job that runs your fuzz targets
12on pull requests. This works similarly to running unit tests in CI. CIFuzz helps
13you find and fix bugs before they make it into your codebase.
14Currently, CIFuzz only supports projects hosted on GitHub.
15
16## How it works
17
18CIFuzz builds your project's fuzzers from the source at a particular
19pull request or commit. Then CIFuzz runs the fuzzers for a short amount of time.
20If CIFuzz finds a crash, CIFuzz reports the stacktrace, makes the crashing
21input available for download and the CI test fails (red X).
22
23If CIFuzz doesn't find a crash during the allotted time, the CI test passes
24(green check). If CIFuzz finds a crash, it reports the crash only if both of following are true:
25* The crash is reproducible (on the PR/commit build).
26* The crash does not occur on older OSS-Fuzz builds. (If the crash does occur
27  on older builds, then it was not introduced by the PR/commit
28  being tested.)
29
30If your project supports [OSS-Fuzz's code coverage]({{ site.baseurl }}/advanced-topics/code-coverage),
31CIFuzz only runs the fuzzers affected by a pull request/commit.
32Otherwise it will divide up the allotted fuzzing time (10 minutes by default)
33among all fuzzers in the project.
34
35CIFuzz uses 30 day old/public regressions and corpora from OSS-Fuzz. This makes
36fuzzing more effective and gives you regression testing for free.
37
38## Requirements
39
401. Your project must be integrated with OSS-Fuzz.
411. Your project is hosted on GitHub.
421. Your repository needs to be cloned with `git` in oss-fuzz Dockerfile (do not use `go get` or other methods)
43
44## Integrating into your repository
45
46You can integrate CIFuzz into your project using the following steps:
471. Create a `.github` directory in the root of your project.
481. Create a `workflows` directory inside of your `.github` directory.
491. Copy the example [`main.yml`](https://github.com/google/oss-fuzz/blob/master/infra/cifuzz/example_main.yml)
50file over from the OSS-Fuzz repository to the `workflows` directory.
511. Change the `oss-fuzz-project-name` value in `main.yml` from `example` to the name of your OSS-Fuzz project. It is **very important** that you use your OSS-Fuzz project name which is case sensitive. This name
52is the name of your project's subdirectory in the [`projects`](https://github.com/google/oss-fuzz/tree/master/projects) directory of OSS-Fuzz.
531. Set the value of `fuzz-seconds`. The longest time that the project maintainers are acceptable with should be used. This value should be at minimum 600 seconds and scale with project size.
54
55Your directory structure should look like the following:
56```
57project
58|___ .github
59|    |____ workflows
60|          |____ main.yml
61|___ other-files
62```
63
64main.yml for an example project:
65
66```yaml
67name: CIFuzz
68on: [pull_request]
69jobs:
70 Fuzzing:
71   runs-on: ubuntu-latest
72   steps:
73   - name: Build Fuzzers
74     id: build
75     uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
76     with:
77       oss-fuzz-project-name: 'example'
78       language: c++
79   - name: Run Fuzzers
80     uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
81     with:
82       oss-fuzz-project-name: 'example'
83       language: c++
84       fuzz-seconds: 600
85   - name: Upload Crash
86     uses: actions/upload-artifact@v1
87     if: failure() && steps.build.outcome == 'success'
88     with:
89       name: artifacts
90       path: ./out/artifacts
91```
92
93
94### Optional configuration
95
96#### Configurable Variables
97
98`language`: (optional) The language your target program is written in. Defaults
99to `c++`. This should be the same as the value you set in `project.yaml`. See
100[this explanation]({{ site.baseurl }}//getting-started/new-project-guide/#language)
101for more details.
102
103`fuzz-time`: Determines how long CIFuzz spends fuzzing your project in seconds.
104The default is 600 seconds. The GitHub Actions max run time is 21600 seconds (6
105hours). This variable is only meaningful when supplied to the `run_fuzzers`
106action, not the `build_fuzzers` action.
107
108`dry-run`: Determines if CIFuzz surfaces errors. The default value is `false`. When set to `true`,
109CIFuzz will never report a failure even if it finds a crash in your project.
110This requires the user to manually check the logs for detected bugs. If dry run mode is desired,
111make sure to set the dry-run parameters in both the `Build Fuzzers` and `Run Fuzzers` action step.
112
113`allowed-broken-targets-percentage`: Can be set if you want to set a stricter
114limit for broken fuzz targets than OSS-Fuzz's check_build. Most users should
115not set this. This value is only meaningful when supplied to the `run_fuzzers`
116action, not the `build_fuzzers` action.
117
118`sanitizer`: Determines a sanitizer to build and run fuzz targets with. The choices are `'address'`,
119`'memory'` and `'undefined'`. The default is `'address'`. It is important to note that the `Build Fuzzers`
120and the `Run Fuzzers` sanitizer field needs to be the same. To specify a list of sanitizers
121a [matrix](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix)
122can be used. To use a sanitizer add it to the list of sanitizers in the matrix field below:
123
124```yaml
125{% raw %}
126name: CIFuzz
127on: [pull_request]
128jobs:
129 Fuzzing:
130   runs-on: ubuntu-latest
131   strategy:
132     fail-fast: false
133     matrix:
134       sanitizer: [address, undefined, memory]
135   steps:
136   - name: Build Fuzzers (${{ matrix.sanitizer }})
137     id: build
138     uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
139     with:
140       oss-fuzz-project-name: 'example'
141       language: c++
142       sanitizer: ${{ matrix.sanitizer }}
143   - name: Run Fuzzers (${{ matrix.sanitizer }})
144     uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
145     with:
146       oss-fuzz-project-name: 'example'
147       language: c++
148       fuzz-seconds: 600
149       sanitizer: ${{ matrix.sanitizer }}
150   - name: Upload Crash
151     uses: actions/upload-artifact@v1
152     if: failure() && steps.build.outcome == 'success'
153     with:
154       name: ${{ matrix.sanitizer }}-artifacts
155       path: ./out/artifacts
156{% endraw %}
157```
158
159#### Branches and paths
160
161You can make CIFuzz trigger only on certain branches or paths by following the
162instructions [here](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions).
163For example, the following code can used to trigger CIFuzz only on changes to
164C/C++ code residing on master and release branches:
165
166```yaml
167name: CIFuzz
168on:
169  pull_request:
170    branches:
171      - master
172      - 'releases/**'
173    paths:
174      - '**.c'
175      - '**.cc'
176      - '**.cpp'
177      - '**.cxx'
178      - '**.h'
179jobs:
180 Fuzzing:
181   runs-on: ubuntu-latest
182   steps:
183   - name: Build Fuzzers
184     id: build
185     uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
186     with:
187       oss-fuzz-project-name: 'example'
188       language: c++
189   - name: Run Fuzzers
190     uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
191     with:
192       oss-fuzz-project-name: 'example'
193       language: c++
194       fuzz-seconds: 600
195   - name: Upload Crash
196     uses: actions/upload-artifact@v1
197     if: failure() && steps.build.outcome == 'success'
198     with:
199       name: artifacts
200       path: ./out/artifacts
201```
202
203You can checkout CIFuzz configs for OSS-Fuzz projects. Example -
204[systemd](https://github.com/systemd/systemd/blob/master/.github/workflows/cifuzz.yml),
205[curl](https://github.com/curl/curl/blob/master/.github/workflows/fuzz.yml).
206
207## Understanding results
208
209The results of CIFuzz can be found in two different places.
210
211* Run fuzzers log:
212    1. This log can be accessed in the `actions` tab of a CIFuzz integrated repo.
213    1. Click on the `CIFuzz` button in the workflow selector on the left hand side.
214    1. Click on the event triggered by your desired pull request.
215    1. Click the `Fuzzing` workflow.
216    1. Select the `Run Fuzzer` drop down. It should show the timestamps and results
217    from each of the fuzz targets.
218
219![Finding fuzzer output](../images/run_fuzzers.png)
220
221
222*  Artifacts:
223    1. When a crash is found by CIFuzz the Upload Artifact event is triggered.
224    1. This will cause a pop up in the right hand corner, allowing
225    you to download a zip file called `artifacts`.
226    1. `artifacts` contains two files for each crash:
227        * A test case that can be used to reproduce the crash.
228        * The sanitizer stack trace of the crash.
229
230![Finding uploaded artifacts](../images/artifacts.png)
231
232
233## Feedback/Questions/Issues
234
235Create an issue in [OSS-Fuzz](https://github.com/google/oss-fuzz/issues/new) if you have questions or any other feedback on CIFuzz.
236