Go supports fuzzing in its standard toolchain beginning in Go 1.18.

Overview

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.

Writing and running fuzz tests

Requirements

Below are rules that fuzz tests must follow.

  • A fuzz test must be a function named like FuzzXxx, which accepts only a *testing.F, and has no return value.
  • Fuzz tests must be in *_test.go files to run.
  • A fuzz target must be a method call to (*testing.F).Fuzz which accepts a *testing.T as the first parameter, followed by the fuzzing arguments. There is no return value.
  • There must be exactly one fuzz target per fuzz test.
  • All seed corpus entries must have types which are identical to the fuzzing arguments, in the same order. This is true for calls to (*testing.F).Add and any corpus files in the testdata/fuzz directory of the fuzz test.
  • The fuzzing arguments can only be the following types:
    • string, []byte
    • int, int8, int16, int32/rune, int64
    • uint, uint8/byte, uint16, uint32, uint64
    • float32, float64
    • bool

Suggestions

Below are suggestions that will help you get the most out of fuzzing.

  • Fuzzing should be run on a platform that supports coverage instrumentation (currently AMD64 and ARM64) so that the corpus can meaningfully grow as it runs, and more code can be covered while fuzzing.
  • Fuzz targets should be fast and deterministic so the fuzzing engine can work efficiently, and new failures and code coverage can be easily reproduced.
  • Since the fuzz target is invoked in parallel across multiple workers and in nondeterministic order, the state of a fuzz target should not persist past the end of each call, and the behavior of a fuzz target should not depend on global state.

Resources

  • Tutorial:
    • For an introductory tutorial of fuzzing with Go, please see the blog post.
    • More to come soon!
  • Documentation:
    • The testing package docs describes the testing.F type which is used when writing fuzz tests.
    • The cmd/go package docs describe the flags associated with fuzzing.
  • Technical details:

Glossary

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.

Feedback

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.