...

Text file src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt

Documentation: cmd/go/testdata/script

     1[!fuzz] skip
     2
     3# Tests that a crash caused by a mutator-discovered input writes the bad input
     4# to testdata, and fails+reports correctly. This tests the end-to-end behavior
     5# of the mutator finding a crash while fuzzing, adding it as a regression test
     6# to the seed corpus in testdata, and failing the next time the test is run.
     7
     8[short] skip
     9env GOCACHE=$WORK/cache
    10
    11# Running the seed corpus for all of the targets should pass the first
    12# time, since nothing in the seed corpus will cause a crash.
    13go test
    14
    15# Running the fuzzer should find a crashing input quickly.
    16! go test -fuzz=FuzzWithBug -fuzztime=100x -fuzzminimizetime=1000x
    17stdout 'testdata[/\\]fuzz[/\\]FuzzWithBug[/\\]'
    18stdout 'this input caused a crash!'
    19go run check_testdata.go FuzzWithBug
    20
    21# Now, the failing bytes should have been added to the seed corpus for
    22# the target, and should fail when run without fuzzing.
    23! go test
    24stdout 'FuzzWithBug/[a-f0-9]{16}'
    25stdout 'this input caused a crash!'
    26
    27! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x -fuzzminimizetime=1000x
    28stdout 'testdata[/\\]fuzz[/\\]FuzzWithNilPanic[/\\]'
    29stdout 'panic called with nil argument|test executed panic.nil. or runtime.Goexit'
    30go run check_testdata.go FuzzWithNilPanic
    31
    32! go test -run=FuzzWithGoexit -fuzz=FuzzWithGoexit -fuzztime=100x -fuzzminimizetime=1000x
    33stdout 'testdata[/\\]fuzz[/\\]FuzzWithGoexit[/\\]'
    34stdout 'runtime.Goexit'
    35go run check_testdata.go FuzzWithGoexit
    36
    37! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x -fuzzminimizetime=1000x
    38stdout 'testdata[/\\]fuzz[/\\]FuzzWithFail[/\\]'
    39go run check_testdata.go FuzzWithFail
    40
    41! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x -fuzzminimizetime=1000x
    42stdout 'testdata[/\\]fuzz[/\\]FuzzWithLogFail[/\\]'
    43stdout 'logged something'
    44go run check_testdata.go FuzzWithLogFail
    45
    46! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=100x -fuzzminimizetime=1000x
    47stdout 'testdata[/\\]fuzz[/\\]FuzzWithErrorf[/\\]'
    48stdout 'errorf was called here'
    49go run check_testdata.go FuzzWithErrorf
    50
    51! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=100x -fuzzminimizetime=1000x
    52stdout 'testdata[/\\]fuzz[/\\]FuzzWithFatalf[/\\]'
    53stdout 'fatalf was called here'
    54go run check_testdata.go FuzzWithFatalf
    55
    56! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x -fuzzminimizetime=1000x
    57stdout 'testdata[/\\]fuzz[/\\]FuzzWithBadExit[/\\]'
    58stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
    59go run check_testdata.go FuzzWithBadExit
    60
    61! go test -run=FuzzDeadlock -fuzz=FuzzDeadlock -fuzztime=100x -fuzzminimizetime=0x
    62stdout 'testdata[/\\]fuzz[/\\]FuzzDeadlock[/\\]'
    63stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
    64go run check_testdata.go FuzzDeadlock
    65
    66# Running the fuzzer should find a crashing input quickly for fuzzing two types.
    67! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x -fuzzminimizetime=1000x
    68stdout 'testdata[/\\]fuzz[/\\]FuzzWithTwoTypes[/\\]'
    69stdout 'these inputs caused a crash!'
    70go run check_testdata.go FuzzWithTwoTypes
    71
    72# Running the fuzzer should find a crashing input quickly for an integer.
    73! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x -fuzzminimizetime=1000x
    74stdout 'testdata[/\\]fuzz[/\\]FuzzInt[/\\]'
    75stdout 'this input caused a crash!'
    76go run check_testdata.go FuzzInt
    77
    78! go test -run=FuzzUint -fuzz=FuzzUint -fuzztime=100x -fuzzminimizetime=1000x
    79stdout 'testdata[/\\]fuzz[/\\]FuzzUint[/\\]'
    80stdout 'this input caused a crash!'
    81go run check_testdata.go FuzzUint
    82
    83# Running the fuzzer should find a crashing input quickly for a bool.
    84! go test -run=FuzzBool -fuzz=FuzzBool -fuzztime=100x -fuzzminimizetime=1000x
    85stdout 'testdata[/\\]fuzz[/\\]FuzzBool[/\\]'
    86stdout 'this input caused a crash!'
    87go run check_testdata.go FuzzBool
    88
    89# Running the fuzzer should find a crashing input quickly for a float.
    90! go test -run=FuzzFloat -fuzz=FuzzFloat -fuzztime=100x -fuzzminimizetime=1000x
    91stdout 'testdata[/\\]fuzz[/\\]FuzzFloat[/\\]'
    92stdout 'this input caused a crash!'
    93go run check_testdata.go FuzzFloat
    94
    95# Running the fuzzer should find a crashing input quickly for a byte.
    96! go test -run=FuzzByte -fuzz=FuzzByte -fuzztime=100x -fuzzminimizetime=1000x
    97stdout 'testdata[/\\]fuzz[/\\]FuzzByte[/\\]'
    98stdout 'this input caused a crash!'
    99go run check_testdata.go FuzzByte
   100
   101# Running the fuzzer should find a crashing input quickly for a rune.
   102! go test -run=FuzzRune -fuzz=FuzzRune -fuzztime=100x -fuzzminimizetime=1000x
   103stdout 'testdata[/\\]fuzz[/\\]FuzzRune[/\\]'
   104stdout 'this input caused a crash!'
   105go run check_testdata.go FuzzRune
   106
   107# Running the fuzzer should find a crashing input quickly for a string.
   108! go test -run=FuzzString -fuzz=FuzzString -fuzztime=100x -fuzzminimizetime=1000x
   109stdout 'testdata[/\\]fuzz[/\\]FuzzString[/\\]'
   110stdout 'this input caused a crash!'
   111go run check_testdata.go FuzzString
   112
   113-- go.mod --
   114module m
   115
   116go 1.16
   117-- fuzz_crash_test.go --
   118package fuzz_crash
   119
   120import (
   121	"os"
   122	"runtime"
   123	"testing"
   124)
   125
   126func FuzzWithBug(f *testing.F) {
   127	f.Add([]byte("aa"))
   128	f.Fuzz(func(t *testing.T, b []byte) {
   129		if string(b) != "aa" {
   130			panic("this input caused a crash!")
   131		}
   132	})
   133}
   134
   135func FuzzWithNilPanic(f *testing.F) {
   136	f.Add([]byte("aa"))
   137	f.Fuzz(func(t *testing.T, b []byte) {
   138		if string(b) != "aa" {
   139			panic(nil)
   140		}
   141	})
   142}
   143
   144func FuzzWithGoexit(f *testing.F) {
   145	f.Add([]byte("aa"))
   146	f.Fuzz(func(t *testing.T, b []byte) {
   147		if string(b) != "aa" {
   148			runtime.Goexit()
   149		}
   150	})
   151}
   152
   153func FuzzWithFail(f *testing.F) {
   154	f.Add([]byte("aa"))
   155	f.Fuzz(func(t *testing.T, b []byte) {
   156		if string(b) != "aa" {
   157			t.Fail()
   158		}
   159	})
   160}
   161
   162func FuzzWithLogFail(f *testing.F) {
   163	f.Add([]byte("aa"))
   164	f.Fuzz(func(t *testing.T, b []byte) {
   165		if string(b) != "aa" {
   166			t.Log("logged something")
   167			t.Fail()
   168		}
   169	})
   170}
   171
   172func FuzzWithErrorf(f *testing.F) {
   173	f.Add([]byte("aa"))
   174	f.Fuzz(func(t *testing.T, b []byte) {
   175		if string(b) != "aa" {
   176			t.Errorf("errorf was called here")
   177		}
   178	})
   179}
   180
   181func FuzzWithFatalf(f *testing.F) {
   182	f.Add([]byte("aa"))
   183	f.Fuzz(func(t *testing.T, b []byte) {
   184		if string(b) != "aa" {
   185			t.Fatalf("fatalf was called here")
   186		}
   187	})
   188}
   189
   190func FuzzWithBadExit(f *testing.F) {
   191	f.Add([]byte("aa"))
   192	f.Fuzz(func(t *testing.T, b []byte) {
   193		if string(b) != "aa" {
   194			os.Exit(1)
   195		}
   196	})
   197}
   198
   199func FuzzDeadlock(f *testing.F) {
   200	f.Add(int(0))
   201	f.Fuzz(func(t *testing.T, n int) {
   202		if n != 0 {
   203			select {}
   204		}
   205	})
   206}
   207
   208func FuzzWithTwoTypes(f *testing.F) {
   209	f.Fuzz(func(t *testing.T, a, b []byte) {
   210		if len(a) > 0 && len(b) > 0 {
   211			panic("these inputs caused a crash!")
   212		}
   213	})
   214}
   215
   216func FuzzInt(f *testing.F) {
   217	f.Add(0)
   218	f.Fuzz(func(t *testing.T, a int) {
   219		if a != 0 {
   220			panic("this input caused a crash!")
   221		}
   222	})
   223}
   224
   225func FuzzUint(f *testing.F) {
   226	f.Add(uint(0))
   227	f.Fuzz(func(t *testing.T, a uint) {
   228		if a != 0 {
   229			panic("this input caused a crash!")
   230		}
   231	})
   232}
   233
   234func FuzzBool(f *testing.F) {
   235	f.Add(false)
   236	f.Fuzz(func(t *testing.T, a bool) {
   237		if a {
   238			panic("this input caused a crash!")
   239		}
   240	})
   241}
   242
   243func FuzzFloat(f *testing.F) {
   244	f.Fuzz(func(t *testing.T, a float64) {
   245		if a != 0 {
   246			panic("this input caused a crash!")
   247		}
   248	})
   249}
   250
   251func FuzzByte(f *testing.F) {
   252	f.Add(byte(0))
   253	f.Fuzz(func(t *testing.T, a byte) {
   254		if a != 0 {
   255			panic("this input caused a crash!")
   256		}
   257	})
   258}
   259
   260func FuzzRune(f *testing.F) {
   261	f.Add(rune(0))
   262	f.Fuzz(func(t *testing.T, a rune) {
   263		if a != 0 {
   264			panic("this input caused a crash!")
   265		}
   266	})
   267}
   268
   269func FuzzString(f *testing.F) {
   270	f.Add("")
   271	f.Fuzz(func(t *testing.T, a string) {
   272		if a != "" {
   273			panic("this input caused a crash!")
   274		}
   275	})
   276}
   277
   278-- check_testdata.go --
   279// +build ignore
   280
   281package main
   282
   283import (
   284	"bytes"
   285	"crypto/sha256"
   286	"fmt"
   287	"io/ioutil"
   288	"os"
   289	"path/filepath"
   290)
   291
   292func main() {
   293	target := os.Args[1]
   294	dir := filepath.Join("testdata/fuzz", target)
   295
   296	files, err := ioutil.ReadDir(dir)
   297	if err != nil {
   298		fmt.Fprintln(os.Stderr, err)
   299		os.Exit(1)
   300	}
   301
   302	if len(files) == 0 {
   303		fmt.Fprintf(os.Stderr, "expect at least one new mutation to be written to testdata\n")
   304		os.Exit(1)
   305	}
   306
   307	fname := files[0].Name()
   308	contents, err := ioutil.ReadFile(filepath.Join(dir, fname))
   309	if err != nil {
   310		fmt.Fprintln(os.Stderr, err)
   311		os.Exit(1)
   312	}
   313	if bytes.Equal(contents, []byte("aa")) {
   314		fmt.Fprintf(os.Stderr, "newly written testdata entry was not mutated\n")
   315		os.Exit(1)
   316	}
   317	// The hash of the bytes in the file should match the filename.
   318	h := []byte(fmt.Sprintf("%x", sha256.Sum256(contents)))
   319	if !bytes.HasPrefix(h, []byte(fname)) {
   320		fmt.Fprintf(os.Stderr, "hash of bytes %q does not match filename %q\n", h, fname)
   321		os.Exit(1)
   322	}
   323}

View as plain text