2019-09-17 14:15:22 +00:00
---
layout: default
title: Integrating a Go project
parent: Setting up a new project
grand_parent: Getting started
nav_order: 1
permalink: /getting-started/new-project-guide/go-lang/
---
# Integrating a Go project
{: .no_toc}
- TOC
{:toc}
---
The process of integrating a project written in Go with OSS-Fuzz is very similar
to the general
[Setting up a new project ]({{ site.baseurl }}/getting-started/new-project-guide/ )
process. The key specifics of integrating a Go project are outlined below.
## Go-fuzz support
OSS-Fuzz supports **go-fuzz** in the
2020-04-14 04:57:30 +00:00
[libFuzzer compatible mode ](https://github.com/mdempsky/go114-fuzz-build )
2019-09-17 14:15:22 +00:00
only. In that mode, fuzz targets for Go use the libFuzzer engine with native Go
coverage instrumentation. Binaries compiled in this mode provide the same
libFuzzer command line interface as non-Go fuzz targets.
2022-02-08 19:57:00 +00:00
## Native Go Fuzzing support
2022-07-22 12:39:20 +00:00
OSS-fuzz supports [fuzzers written for the native Go 1.18 engine ](https://go.dev/doc/fuzz/ ). These fuzzers are built as libFuzzer binaries in a similar fashion as fuzzers written for the go-fuzz engine. Because of that, dictionaries and seed corpora should be handled in accordance with [the OSS-fuzz documentation ](https://google.github.io/oss-fuzz/getting-started/new-project-guide/#seed-corpus ).
2022-02-08 19:57:00 +00:00
Unlike libFuzzer/go-fuzz targets which must accept one data buffer, fuzz targets written for the Native Go engine can accept any number of arguments of any type. Here is an example of a valid fuzzer with multiple arguments:
```go
package demofuzzing
import (
"fmt"
"testing"
)
func FuzzDemo(f *testing.F) {
f.Fuzz(func(t *testing.T, data1 string, data2 uint32, data3 float64) {
fmt.Println(data1)
fmt.Println(data2)
fmt.Println(data3)
})
}
```
Some requirements for native Go 1.18 fuzzers are:
* The only `testing.F` method supported is currently `F.Fuzz()` .
* `F.Add()` will not add seeds when fuzzing. To provide OSS-fuzz with a seed corpus, follow the documentation [here ](https://google.github.io/oss-fuzz/getting-started/new-project-guide/#seed-corpus ).
2019-09-17 14:15:22 +00:00
## Project files
2022-02-08 19:57:00 +00:00
First, you need to write a Go fuzz target. This fuzz target should reside in your project
2020-04-14 04:57:30 +00:00
repository
([example](https://github.com/golang/go/blob/4ad13555184eb0697c2e92c64c1b0bdb287ccc10/src/html/fuzz.go#L13)).
2019-09-17 14:15:22 +00:00
The structure of the project directory in OSS-Fuzz repository doesn't differ for
2020-01-30 23:36:44 +00:00
projects written in Go. The project files have the following Go specific
aspects.
2019-09-17 14:15:22 +00:00
### project.yaml
2020-01-30 23:36:44 +00:00
The `language` attribute must be specified.
```yaml
language: go
```
The only supported fuzzing engine and sanitizer are `libfuzzer` and `address` ,
respectively.
2019-09-17 14:15:22 +00:00
[Example ](https://github.com/google/oss-fuzz/blob/356f2b947670b7eb33a1f535c71bc5c87a60b0d1/projects/syzkaller/project.yaml#L7 ):
```yaml
fuzzing_engines:
- libfuzzer
sanitizers:
- address
```
### Dockerfile
2021-09-08 16:13:52 +00:00
The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-go`
2019-09-17 14:15:22 +00:00
The OSS-Fuzz builder image has the latest stable release of Golang installed. In
2021-02-22 23:25:47 +00:00
order to install dependencies of your project, add `RUN git clone ...` command to
2019-09-17 14:15:22 +00:00
your Dockerfile.
[Example ](https://github.com/google/oss-fuzz/blob/356f2b947670b7eb33a1f535c71bc5c87a60b0d1/projects/syzkaller/Dockerfile#L23 ):
```dockerfile
# Dependency for one of the fuzz targets.
2021-02-22 23:25:47 +00:00
RUN git clone --depth 1 https://github.com/ianlancetaylor/demangle
2019-09-17 14:15:22 +00:00
```
2021-02-22 23:25:47 +00:00
go-fuzz will then automatically download the dependencies based on the go.mod file
2020-11-25 15:40:15 +00:00
2019-09-17 14:15:22 +00:00
### build.sh
2020-04-14 04:57:30 +00:00
In order to build a Go fuzz target, you need to call `go-fuzz`
2019-09-17 14:15:22 +00:00
command first, and then link the resulting `.a` file against
`$LIB_FUZZING_ENGINE` using the `$CXX $CXXFLAGS ...` command.
2022-07-23 16:09:33 +00:00
For go-fuzz fuzzers, the best way to do this is by using the [`compile_go_fuzzer` script ](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_go_fuzzer ), and for native Go 1.18 fuzzers it is recommended to use the [`compile_native_go_fuzzer` script ](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_native_go_fuzzer ). Both of these also support coverage builds.
2019-09-17 14:15:22 +00:00
2022-08-05 14:36:22 +00:00
`compile_native_go_fuzzer` requires two dependencies which can be installed with:
```bash
go install github.com/AdamKorcz/go-118-fuzz-build@latest
2022-11-21 17:55:11 +00:00
go get github.com/AdamKorcz/go-118-fuzz-build/testing
2022-08-05 14:36:22 +00:00
```
2020-11-20 18:55:33 +00:00
A usage example from go-dns project is
2019-09-17 14:15:22 +00:00
2020-11-20 18:55:33 +00:00
```sh
compile_go_fuzzer github.com/miekg/dns FuzzNewRR fuzz_newrr fuzz
2019-09-17 14:15:22 +00:00
```
2020-11-20 18:55:33 +00:00
Arguments are :
* path of the package with the fuzz target
* name of the fuzz function
* name of the fuzzer to be built
* optional tag to be used by `go build` and such