Documentation ¶
Overview ¶
Package fuzz defines the API used by fzgo (a simple prototype of integrating dvyukov/go-fuzz into 'go test').
See the README at https://github.com/thepudds/fzgo for more details.
Index ¶
- Variables
- func CacheDir(hash, pkgName, fuzzName string) string
- func CopyDir(dst string, src string) error
- func CopyFile(dst string, src string) error
- func ExecGo(args []string, env []string) error
- func FindFlag(args []string, names []string) (string, string, bool)
- func FindPkgs(args []string) ([]string, []string, error)
- func FindTestFlag(args []string, names []string) (string, string, bool)
- func FlagSet(name string, defs []FlagDef, usage Usage) (*flag.FlagSet, error)
- func Gopath() string
- func Hash(pkgPath, funcName, trimPrefix string, env []string, verbose bool) (string, error)
- func IsPlainSig(f *types.Func) (bool, error)
- func ParseArgs(args []string, fs *flag.FlagSet) (string, error)
- func PathExists(path string) bool
- func Start(target Target, workDir string, maxDuration time.Duration, parallel int, ...) error
- func VerifyCorpus(function Func, workDir string, run string, verbose bool) error
- type FlagDef
- type Func
- type Target
- type Usage
Constants ¶
This section is empty.
Variables ¶
var ErrGoTestFailed = errors.New("go test failed")
ErrGoTestFailed indicates that a 'go test' invocation failed, most likely because the test had a legitimate failure.
var IncompatibleTestFlags = []string{
"args",
"bench",
"benchmem",
"benchtime",
"blockprofile",
"blockprofilerate",
"count",
"cover",
"covermode",
"coverpkg",
"cpu",
"cpuprofile",
"exec",
"failfast",
"json",
"list",
"memprofile",
"memprofilerate",
"mutexprofile",
"mutexprofilefraction",
"o",
"outputdir",
"short",
"trace",
"vet",
}
IncompatibleTestFlags is a list of 'go test' flags that might be incompatible with a final 'go test -fuzz' based on the March 2017 proposal document. These currently cause an error if 'fzgo test -fuzz' is also specified. This list likely would change based on more discussion of the proposal.
var UnimplementedBuildFlags = []string{
"a",
"asmflags",
"buildmode",
"compiler",
"gccgoflags",
"gcflags",
"installsuffix",
"ldflags",
"linkshared",
"mod",
"msan",
"n",
"p",
"pkgdir",
"race",
"tags",
"toolexec",
"work",
"x",
}
UnimplementedBuildFlags is a list of 'go test' build flags that are not implemented in this simple 'fzgo' prototype; these will cause an error if used with 'fzgo test -fuzz'. (If 'test -fuzz' is not specified, 'fzgo' will pass any of these arguments through to the actual 'go' tool).
var UnimplementedTestFlags = []string{
"coverprofile",
"i",
}
UnimplementedTestFlags is a list of 'go test' flags that are expected to be eventually be compatible with a final 'go test -fuzz' per the March 2017 proposal document, but which are not currently implemented in this simple 'fzgo' prototype. These will currently cause an error if used with 'fzgo test -fuzz'.
Functions ¶
func CopyDir ¶
CopyDir is a simple implementation of recursively copying a directory. The main use case is copying a corpus directory (which does not have symlinks, etc.). Files that already exist in the destination are left alone.
func CopyFile ¶
CopyFile copies a file. A dst file that already exists is left alone, and is not an error. The main use case is updating a corpus from GOPATH/pkg/fuzz/corpus/..., and we trust the destination if the file already exists.
func ExecGo ¶
ExecGo invokes the go command. The intended use case is fzgo operating in pass-through mode, where an invocation like 'fzgo env GOPATH' gets passed to the 'go' tool as 'go env GOPATH'. args typically would be os.Args[1:]
func FindFlag ¶
FindFlag looks for the first matching arg that looks like a flag in the list of flag names, and returns the first flag name found. FindFlag does not stop at non-flag arguments (e.g., it does not stop at a package pattern). This is a simple scan, and not a complete parse of the arguments (and for example does not differentiate between a bool flag vs. a duration flag). A client should do a final valiation pass via fuzz.ParseArgs(), which calls the standard flag.FlagSet.Parse() and which will reject malformed arguments according to the normal rules of the flag package. Returns the found name, and a possible value that is either the value of name=value, or the next arg if there is no '=' immediately after name. It is up to the caller to know if the possible value should be interpreted as the actual value (because, for example, FindFlag has no knowledge of bool flag vs. other flags, etc.).
func FindPkgs ¶
FindPkgs looks for args that seem to be package arguments and returns them in a slice.
func FindTestFlag ¶
FindTestFlag looks for the first matching arg that looks like a flag in the list of flag names, and returns the first flag name found. If passed flag name 'foo', it looks for both '-foo' and '-test.foo'. See FindFlag for more details.
func FlagSet ¶
FlagSet creates a new flag.FlagSet and registers our flags. Each flag is registered once as "foo" and once as "test.foo"
func Gopath ¶
func Gopath() string
Gopath returns the current effective GOPATH (from the GOPATH env, or the default if env var now set).
func Hash ¶
Hash returns a string representing the hash of the files in a package, its dependencies, as well as the fuzz func name, the version of go and the go-fuzz-build binary.
func IsPlainSig ¶
IsPlainSig reports whether a signature is a classic, plain 'func([]bytes) int' go-fuzz signature.
func ParseArgs ¶
ParseArgs finds the flags we are going to interpret and sets the values in a flag.FlagSet. ParseArgs handles a package pattern that might appear in the middle of args in order to allow the flag.FlagSet.Parse() to find flags after the package pattern. ParseArgs also returns at most one package pattern, or "." if none was specified in args.
func Start ¶
func Start(target Target, workDir string, maxDuration time.Duration, parallel int, funcTimeout time.Duration, v bool) error
Start begins fuzzing by invoking 'go-fuzz'. cacheDir contains the instrumented binary, and would typically be something like:
GOPATH/pkg/fuzz/linux_amd64/619f7d77e9cd5d7433f8/fmt.FuzzFmt
workDir contains the corpus, and would typically be something like:
GOPATH/src/github.com/user/proj/testdata/fuzz/fmt.FuzzFmt
func VerifyCorpus ¶
VerifyCorpus runs all of the files in a corpus directory as subtests. The approach is to create a temp dir, then create a synthetic corpus_test.go file with a TestCorpus(t *testing.T) func that loads all the files from the corpus, and passes them to the Fuzz function in a t.Run call. A standard 'go test .' is then invoked within that temporary directory. The inputs used are all deterministic (without generating new fuzzing-based inputs). The names used with t.Run mean a 'fzgo test -run=TestCorpus/<corpus-file-name>' works. One way to see the file names or otherwise verify execution is to run 'fzgo test -v <pkg>'.
Types ¶
type FlagDef ¶
type FlagDef struct { Name string Ptr interface{} // *string, *bool, *int, or *time.Duration Description string }
FlagDef holds the definition of an arg we will interpret.
type Func ¶
type Func struct { FuncName string PkgName string // package name (should be the same as the package's package statement) PkgPath string // import path PkgDir string // local on-disk directory TypesFunc *types.Func // auxiliary information about a Func from the go/types package }
Func represents a discovered function that will be fuzzed.
func FindFunc ¶
FindFunc searches for a requested function to fuzz. It is not an error to not find any -- in that case, it returns a nil list and nil error. The March 2017 proposal document https://github.com/golang/go/issues/19109#issuecomment-285456008 suggests not allowing something like 'go test -fuzz=. ./...' to match multiple fuzz functions. As an experiment, allowMultiFuzz flag allows that. FindFunc also allows for multiple packages in pkgPattern separated by whitespace.
type Target ¶
type Target struct { UserFunc Func // the user's original function // contains filtered or unexported fields }
Target tracks some metadata about each fuzz target, and is responsible for tracking a fuzz.Func found via go/packages and making it useful as a fuzz target, including determining where to cache the fuzz.zip and what the target's fuzzName should be.
func CreateRichSigWrapper ¶
CreateRichSigWrapper creates a temp working directory, then creates a rich signature wrapping fuzz function. Important: don't set printArgs=true when actually fuzzing. (Likely bad for perf, though not yet attempted).
func Instrument ¶
Instrument builds the instrumented binary and fuzz.zip if they do not already exist in the fzgo cache. If instead there is a cache hit, Instrument prints to stderr that the cached is being used. cacheDir is the location for the instrumented binary, and would typically be something like:
GOPATH/pkg/fuzz/linux_amd64/619f7d77e9cd5d7433f8/fmt.FuzzFmt