Go supports fuzzing in its standard toolchain beginning in Go 1.18.
Fuzzing is a type of automated testing which continuously manipulates inputs to a program to find bugs. Go fuzzing uses coverage guidance to intelligently walk through the code being fuzzed to find and report failures to the user. Since it can reach edge cases which humans often miss, fuzz testing can be particularly valuable for finding security exploits and vulnerabilities.
Below is an example of a fuzz test, highlighting it's main components.
Below are rules that fuzz tests must follow.
FuzzXxx
, which accepts only a *testing.F
, and has no return value.*testing.T
as the first parameter, followed by the fuzzing arguments. There is no return value.string
, []byte
int
, int8
, int16
, int32
/rune
, int64
uint
, uint8
/byte
, uint16
, uint32
, uint64
float32
, float64
bool
Below are suggestions that will help you get the most out of fuzzing.
The default go command settings should work for most use cases of fuzzing. So typically, an execution of fuzzing on the command line should look like this:
$ go test -fuzz={FuzzTestName}
However, the go
command does provide a few settings when running fuzzing. These are documented in the cmd/go
package docs.
To highlight a few:
-fuzztime
: the total time or number of iterations that the fuzz target will be executed before exiting, default indefinitely.-fuzzminimizetime
: the time or number of iterations that the fuzz target will be executed during each minimization attempt, default 60sec. You can completely disable minimization by setting -fuzzminimizetime 0
when fuzzing.-parallel
: the number of fuzzing processes running at once, default $GOMAXPROCS
. Currently, setting -cpu during fuzzing has no effect.Corpus files are encoded in a special format. This is the same format for both the seed corpus, and the generated corpus.
Below is an example of a corpus file:
go test fuzz v1 []byte("hello\\xbd\\xb2=\\xbc ⌘") int64(572293)
The first line is used to inform the fuzzing engine of the file's encoding version. Although no future versions of the encoding format are currently planned, the design must support this possibility.
Each of the lines following are the values that make up the corpus entry, and can be copied directly into Go code if desired.
In the example above, we have a []byte
followed by an int64
. These types must match the fuzzing arguments exactly, in that order. A fuzz target for these types would look like this:
f.Fuzz(func(*testing.T, []byte, int64) {})
The easiest way to specify your own seed corpus values is to use the (*testing.F).Add
method. In the example above, that would look like this:
f.Add([]byte("hello\\xbd\\xb2=\\xbc ⌘"), int64(572293))
However, you may have large binary files that you'd prefer not to copy as code into your test, and instead remain as individual seed corpus entries in the testdata/fuzz/{FuzzTestName} directory. The file2fuzz
tool at golang.org/x/tools/cmd/file2fuzz can be used to convert these binary files to corpus files encoded for []byte
.
To use this tool:
$ go install golang.org/x/tools/cmd/file2fuzz@latest $ file2fuzz
corpus entry: An input in the corpus which can be used while fuzzing. This can be a specially-formatted file, or a call to (*testing.F).Add.
coverage guidance: A method of fuzzing which uses expansions in code coverage to determine which corpus entries are worth keeping for future use.
fuzz target: The function of the fuzz test which is executed for corpus entries and generated values while fuzzing. It is provided to the fuzz test by passing the function to (*testing.F).Fuzz.
fuzz test: A function in a test file of the form func FuzzXxx(*testing.F)
which can be used for fuzzing.
fuzzing: A type of automated testing which continuously manipulates inputs to a program to find issues such as bugs or vulnerabilities to which the code may be susceptible.
fuzzing arguments: The types which will be passed to the fuzz target, and mutated by the mutator.
fuzzing engine: A tool that manages fuzzing, including maintaining the corpus, invoking the mutator, identifying new coverage, and reporting failures.
generated corpus: A corpus which is maintained by the fuzzing engine over time while fuzzing to keep track of progress. It is stored in $GOCACHE
/fuzz.
mutator: A tool used while fuzzing which randomly manipulates corpus entries before passing them to a fuzz target.
package: A collection of source files in the same directory that are compiled together. See the Packages section in the Go Language Specification.
seed corpus: A user-provided corpus for a fuzz test which can be used to guide the fuzzing engine. It is composed of the corpus entries provided by f.Add calls within the fuzz test, and the files in the testdata/fuzz/{FuzzTestName} directory within the package.
test file: A file of the format xxx_test.go that may contain tests, benchmarks, examples and fuzz tests.
vulnerability: A security-sensitive weakness in code which can be exploited by an attacker.
If you experience any problems or have an idea for a feature, please file an issue.
For discussion and general feedback about the feature, you can also participate in the #fuzzing channel in Gophers Slack.