fuzzdump

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2022 License: MPL-2.0 Imports: 7 Imported by: 0

README

go-fuzzdump

godoc-badge release-badge license-badge goreport-badge

Dump a Go fuzz corpus

A simplistic utility to dump the contents of a Go generated fuzz test corpus.

I was curious whether I could use fuzzing to improve the coverage of my existing tests by discovering more "interesting" inputs. But the format of how a fuzz corpus is cached by Go (a single separate file for every unique argument set) felt a bit unwieldy to be reviewed.

I tried looking for a ready-made solution that would fit the bill for me, but couldn't find any. So I wrote this.

See the reference docs for details.

CLI

Installation
go install github.com/antichris/go-fuzzdump/cmd/fuzzdump@latest
Operation

The fuzzdump command takes a fuzzing corpus directory path as an argument and dumps the corpus entries it finds there to the standard output.

Example
$ fuzzdump ./fuzz/FuzzMyFunc
{{
	string("foo"),
	uint(8),
}, {
	string("bar"),
	uint(13),
}, {
	string("qux"),
	uint(21),
}}
Exit status
Code Description
0 Success
1 Some files were invalid, but others could be dumped
2 No valid corpus files were found
3 Another critical error occurred

License

The source code of this project is released under Mozilla Public License Version 2.0. See LICENSE.

Documentation

Overview

Package fuzzdump implements dumping a generated Go fuzzing corpus.

The output format of a single-argument corpus is similar to a plain slice with the type omitted, e.g.:

{
	int(2),
	int(3),
	int(5),
	// ... etc.
}

The output format of a multiple-argument corpus is similar to a slice of structs, again, with the type omitted, e.g.:

{{
	int(8),
	string("foo"),
}, {
	int(13),
	string("bar"),
}, {
	int(21),
	string("qux"),
	// ... etc.
}}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func DumpDir

func DumpDir(w io.Writer, fsys fs.FS, dir string) (err error)

DumpDir writes the entries from a fuzz test corpus directory to w.

It uses the first valid corpus entry it encounters to determine the number of fuzz arguments all entries should provide, and, consequently, whether to format the output as a single or multiple argument corpus.

If the directory is empty, it returns ErrEmptyCorpus.

An entry with a different number of arguments than initially detected is not dumped, but reported with an ErrInconsistentArgCount in CorpusErrors returned after all files in the directory have been processed.

If any validation errors (such as ErrMalformedEntry or ErrUnsupportedVersion) occurred during the parsing of the directory contents, a CorpusErrors listing the respective errors is returned after all files in the directory have been processed.

If no valid corpus files were found, it returns an ErrEmptyCorpus wrapped in CorpusErrors, along with all the validation errors that occurred.

If any other error occurred during an I/O operation, it may be wrapped by a fmt.Errorf.

Do use errors.Is when checking the returned errors.

func IsValidationError

func IsValidationError(err error) bool

IsValidationError returns true if err is one of the entry validation errors (ErrMalformedEntry, ErrUnsupportedVersion or ErrInconsistentArgCount).

Types

type CorpusErrors

type CorpusErrors []error

CorpusErrors is a collection of errors found in the fuzz corpus while reading it from the file system.

func (CorpusErrors) AsError

func (e CorpusErrors) AsError() error

AsError returns e if errors are present, otherwise it returns nil.

func (*CorpusErrors) Capture

func (e *CorpusErrors) Capture(err error) error

Capture non-critical errors, pass critical ones.

When err is one of the entry validation errors (ErrMalformedEntry or ErrUnsupportedVersion, ErrInconsistentArgCount), it is appended to e and nil is returned.

When err is ErrEmptyCorpus, it also gets appended to e, but since it occurs when corpus is not usable, the whole e is returned as an error instead.

When err is another CorpusErrors instance, each of the errors it holds is processed as above. So a single ErrEmptyCorpus would propagate aborts up the stack of CorpusErrors.Capture's.

Any other error is returned as it is.

Example
malformed := func(name string) error {
	return fmt.Errorf("parsing %q: %w", name, ErrMalformedEntry)
}
badVersion := func(name string) error {
	return fmt.Errorf("parsing %q: %w", name, ErrUnsupportedVersion)
}
fn := func() error {
	var errs CorpusErrors

	// Perform operations that return errors.
	err := malformed("foo")
	if e := errs.Capture(err); e != nil {
		return e
	}
	err = badVersion("bar")
	if e := errs.Capture(err); e != nil {
		return e
	}
	// Execution will continue, as long as the captured error is not
	// a critical one.
	fmt.Println("hello world")

	// Rinse and repeat, as needed.

	return errs.AsError()
}
fmt.Println(fn())
Output:

hello world
fuzz corpus has errors:
	parsing "foo": must include version and at least one value
	parsing "bar": unsupported encoding version

func (CorpusErrors) Error

func (e CorpusErrors) Error() string

Implements the [error] interface.

func (CorpusErrors) Is

func (e CorpusErrors) Is(target error) bool

Is reports whether any error in e matches target. Implements the interface required by errors.Is.

When target is CorpusErrors, it returns true if both target and e are empty, or if e has all the errors that target has.

func (CorpusErrors) Unwrap

func (e CorpusErrors) Unwrap() error

Unwrap returns e without its last error, or nil if e is empty. Implements the interface required by errors.Unwrap.

type Error added in v0.2.0

type Error string

Error is a plain string type and can be used to define a constant.

const ErrEmptyCorpus Error = "no valid fuzz corpus files in directory"

ErrEmptyCorpus is returned when there are no files in fuzz corpus.

const ErrInconsistentArgCount Error = "inconsistent arg count in corpus entry"

ErrInconsistentArgCount is returned when a corpus entry provides a different number of arguments than what was first detected.

This should not occur in practice in corpus data generated by Go.

const ErrMalformedEntry Error = "must include version and at least one value"

ErrMalformedEntry is returned when a corpus entry does not have a supported format.

const ErrUnsupportedVersion Error = "unsupported encoding version"

ErrUnsupportedVersion is returned when a corpus entry does not have a supported version header.

func (Error) Error added in v0.2.0

func (e Error) Error() string

Implements the [error] interface.

Directories

Path Synopsis
cmd
fuzzdump
FuzzDump dumps the entries of a fuzz test corpus directory to the standard output.
FuzzDump dumps the entries of a fuzz test corpus directory to the standard output.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL