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

     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
     9  
    10  # Running the seed corpus for all of the targets should pass the first
    11  # time, since nothing in the seed corpus will cause a crash.
    12  go test
    13  
    14  # Running the fuzzer should find a crashing input quickly.
    15  ! go test -fuzz=FuzzWithBug -fuzztime=100x -fuzzminimizetime=1000x
    16  stdout 'testdata[/\\]fuzz[/\\]FuzzWithBug[/\\]'
    17  stdout 'this input caused a crash!'
    18  go run check_testdata.go FuzzWithBug
    19  
    20  # Now, the failing bytes should have been added to the seed corpus for
    21  # the target, and should fail when run without fuzzing.
    22  ! go test
    23  stdout 'FuzzWithBug/[a-f0-9]{64}'
    24  stdout 'this input caused a crash!'
    25  
    26  ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x -fuzzminimizetime=1000x
    27  stdout 'testdata[/\\]fuzz[/\\]FuzzWithNilPanic[/\\]'
    28  stdout 'runtime.Goexit'
    29  go run check_testdata.go FuzzWithNilPanic
    30  
    31  ! go test -run=FuzzWithGoexit -fuzz=FuzzWithGoexit -fuzztime=100x -fuzzminimizetime=1000x
    32  stdout 'testdata[/\\]fuzz[/\\]FuzzWithGoexit[/\\]'
    33  stdout 'runtime.Goexit'
    34  go run check_testdata.go FuzzWithGoexit
    35  
    36  ! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x -fuzzminimizetime=1000x
    37  stdout 'testdata[/\\]fuzz[/\\]FuzzWithFail[/\\]'
    38  go run check_testdata.go FuzzWithFail
    39  
    40  ! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x -fuzzminimizetime=1000x
    41  stdout 'testdata[/\\]fuzz[/\\]FuzzWithLogFail[/\\]'
    42  stdout 'logged something'
    43  go run check_testdata.go FuzzWithLogFail
    44  
    45  ! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=100x -fuzzminimizetime=1000x
    46  stdout 'testdata[/\\]fuzz[/\\]FuzzWithErrorf[/\\]'
    47  stdout 'errorf was called here'
    48  go run check_testdata.go FuzzWithErrorf
    49  
    50  ! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=100x -fuzzminimizetime=1000x
    51  stdout 'testdata[/\\]fuzz[/\\]FuzzWithFatalf[/\\]'
    52  stdout 'fatalf was called here'
    53  go run check_testdata.go FuzzWithFatalf
    54  
    55  ! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x -fuzzminimizetime=1000x
    56  stdout 'testdata[/\\]fuzz[/\\]FuzzWithBadExit[/\\]'
    57  stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
    58  go run check_testdata.go FuzzWithBadExit
    59  
    60  ! go test -run=FuzzDeadlock -fuzz=FuzzDeadlock -fuzztime=100x -fuzzminimizetime=0x
    61  stdout 'testdata[/\\]fuzz[/\\]FuzzDeadlock[/\\]'
    62  stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
    63  go run check_testdata.go FuzzDeadlock
    64  
    65  # Running the fuzzer should find a crashing input quickly for fuzzing two types.
    66  ! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x -fuzzminimizetime=1000x
    67  stdout 'testdata[/\\]fuzz[/\\]FuzzWithTwoTypes[/\\]'
    68  stdout 'these inputs caused a crash!'
    69  go run check_testdata.go FuzzWithTwoTypes
    70  
    71  # Running the fuzzer should find a crashing input quickly for an integer.
    72  ! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x -fuzzminimizetime=1000x
    73  stdout 'testdata[/\\]fuzz[/\\]FuzzInt[/\\]'
    74  stdout 'this input caused a crash!'
    75  go run check_testdata.go FuzzInt
    76  
    77  ! go test -run=FuzzUint -fuzz=FuzzUint -fuzztime=100x -fuzzminimizetime=1000x
    78  stdout 'testdata[/\\]fuzz[/\\]FuzzUint[/\\]'
    79  stdout 'this input caused a crash!'
    80  go run check_testdata.go FuzzUint
    81  
    82  # Running the fuzzer should find a crashing input quickly for a bool.
    83  ! go test -run=FuzzBool -fuzz=FuzzBool -fuzztime=100x -fuzzminimizetime=1000x
    84  stdout 'testdata[/\\]fuzz[/\\]FuzzBool[/\\]'
    85  stdout 'this input caused a crash!'
    86  go run check_testdata.go FuzzBool
    87  
    88  # Running the fuzzer should find a crashing input quickly for a float.
    89  ! go test -run=FuzzFloat -fuzz=FuzzFloat -fuzztime=100x -fuzzminimizetime=1000x
    90  stdout 'testdata[/\\]fuzz[/\\]FuzzFloat[/\\]'
    91  stdout 'this input caused a crash!'
    92  go run check_testdata.go FuzzFloat
    93  
    94  # Running the fuzzer should find a crashing input quickly for a byte.
    95  ! go test -run=FuzzByte -fuzz=FuzzByte -fuzztime=100x -fuzzminimizetime=1000x
    96  stdout 'testdata[/\\]fuzz[/\\]FuzzByte[/\\]'
    97  stdout 'this input caused a crash!'
    98  go run check_testdata.go FuzzByte
    99  
   100  # Running the fuzzer should find a crashing input quickly for a rune.
   101  ! go test -run=FuzzRune -fuzz=FuzzRune -fuzztime=100x -fuzzminimizetime=1000x
   102  stdout 'testdata[/\\]fuzz[/\\]FuzzRune[/\\]'
   103  stdout 'this input caused a crash!'
   104  go run check_testdata.go FuzzRune
   105  
   106  # Running the fuzzer should find a crashing input quickly for a string.
   107  ! go test -run=FuzzString -fuzz=FuzzString -fuzztime=100x -fuzzminimizetime=1000x
   108  stdout 'testdata[/\\]fuzz[/\\]FuzzString[/\\]'
   109  stdout 'this input caused a crash!'
   110  go run check_testdata.go FuzzString
   111  
   112  -- go.mod --
   113  module m
   114  
   115  go 1.16
   116  -- fuzz_crash_test.go --
   117  package fuzz_crash
   118  
   119  import (
   120  	"os"
   121  	"runtime"
   122  	"testing"
   123  )
   124  
   125  func FuzzWithBug(f *testing.F) {
   126  	f.Add([]byte("aa"))
   127  	f.Fuzz(func(t *testing.T, b []byte) {
   128  		if string(b) != "aa" {
   129  			panic("this input caused a crash!")
   130  		}
   131  	})
   132  }
   133  
   134  func FuzzWithNilPanic(f *testing.F) {
   135  	f.Add([]byte("aa"))
   136  	f.Fuzz(func(t *testing.T, b []byte) {
   137  		if string(b) != "aa" {
   138  			panic(nil)
   139  		}
   140  	})
   141  }
   142  
   143  func FuzzWithGoexit(f *testing.F) {
   144  	f.Add([]byte("aa"))
   145  	f.Fuzz(func(t *testing.T, b []byte) {
   146  		if string(b) != "aa" {
   147  			runtime.Goexit()
   148  		}
   149  	})
   150  }
   151  
   152  func FuzzWithFail(f *testing.F) {
   153  	f.Add([]byte("aa"))
   154  	f.Fuzz(func(t *testing.T, b []byte) {
   155  		if string(b) != "aa" {
   156  			t.Fail()
   157  		}
   158  	})
   159  }
   160  
   161  func FuzzWithLogFail(f *testing.F) {
   162  	f.Add([]byte("aa"))
   163  	f.Fuzz(func(t *testing.T, b []byte) {
   164  		if string(b) != "aa" {
   165  			t.Log("logged something")
   166  			t.Fail()
   167  		}
   168  	})
   169  }
   170  
   171  func FuzzWithErrorf(f *testing.F) {
   172  	f.Add([]byte("aa"))
   173  	f.Fuzz(func(t *testing.T, b []byte) {
   174  		if string(b) != "aa" {
   175  			t.Errorf("errorf was called here")
   176  		}
   177  	})
   178  }
   179  
   180  func FuzzWithFatalf(f *testing.F) {
   181  	f.Add([]byte("aa"))
   182  	f.Fuzz(func(t *testing.T, b []byte) {
   183  		if string(b) != "aa" {
   184  			t.Fatalf("fatalf was called here")
   185  		}
   186  	})
   187  }
   188  
   189  func FuzzWithBadExit(f *testing.F) {
   190  	f.Add([]byte("aa"))
   191  	f.Fuzz(func(t *testing.T, b []byte) {
   192  		if string(b) != "aa" {
   193  			os.Exit(1)
   194  		}
   195  	})
   196  }
   197  
   198  func FuzzDeadlock(f *testing.F) {
   199  	f.Add(int(0))
   200  	f.Fuzz(func(t *testing.T, n int) {
   201  		if n != 0 {
   202  			select {}
   203  		}
   204  	})
   205  }
   206  
   207  func FuzzWithTwoTypes(f *testing.F) {
   208  	f.Fuzz(func(t *testing.T, a, b []byte) {
   209  		if len(a) > 0 && len(b) > 0 {
   210  			panic("these inputs caused a crash!")
   211  		}
   212  	})
   213  }
   214  
   215  func FuzzInt(f *testing.F) {
   216  	f.Add(0)
   217  	f.Fuzz(func(t *testing.T, a int) {
   218  		if a != 0 {
   219  			panic("this input caused a crash!")
   220  		}
   221  	})
   222  }
   223  
   224  func FuzzUint(f *testing.F) {
   225  	f.Add(uint(0))
   226  	f.Fuzz(func(t *testing.T, a uint) {
   227  		if a != 0 {
   228  			panic("this input caused a crash!")
   229  		}
   230  	})
   231  }
   232  
   233  func FuzzBool(f *testing.F) {
   234  	f.Add(false)
   235  	f.Fuzz(func(t *testing.T, a bool) {
   236  		if a {
   237  			panic("this input caused a crash!")
   238  		}
   239  	})
   240  }
   241  
   242  func FuzzFloat(f *testing.F) {
   243  	f.Fuzz(func(t *testing.T, a float64) {
   244  		if a != float64(int64(a)) {
   245  			// It has a decimal, so it was mutated by division
   246  			panic("this input caused a crash!")
   247  		}
   248  	})
   249  }
   250  
   251  func 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  
   260  func 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  
   269  func 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  
   281  package main
   282  
   283  import (
   284  	"bytes"
   285  	"crypto/sha256"
   286  	"fmt"
   287  	"io/ioutil"
   288  	"os"
   289  	"path/filepath"
   290  )
   291  
   292  func 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.Equal([]byte(fname), h) {
   320  		fmt.Fprintf(os.Stderr, "hash of bytes %q does not match filename %q\n", h, fname)
   321  		os.Exit(1)
   322  	}
   323  }
   324  

View as plain text