]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.fuzz] internal/fuzz: don't panic if types change
authorKatie Hockman <katie@golang.org>
Tue, 27 Apr 2021 18:34:17 +0000 (14:34 -0400)
committerKatie Hockman <katie@golang.org>
Tue, 4 May 2021 18:57:18 +0000 (18:57 +0000)
There was a bug where if the types to fuzz were
different from the types in a file in the on-disk
corpus, then the code would panic. We thought
this case was handled, but the final `continue`
in the nested loop still allowed the invalid
entry to be added to the corpus. Pulling the
validation into a helper function makes this
less brittle.

Change-Id: I401346f890ea30ab7cff9640cb555da2e3ff8cc6
Reviewed-on: https://go-review.googlesource.com/c/go/+/313810
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
src/cmd/go/testdata/script/test_fuzz.txt
src/internal/fuzz/fuzz.go

index bfa1b68c67b508e3a74a29893d6fd697fbacc3c2..0b1b85f397b7bbab1dd203103f9b7eaec4e4967d 100644 (file)
@@ -154,6 +154,11 @@ stdout ok
 ! stdout FAIL
 ! stdout 'fatal here'
 
+# Test fails with file containing wrong type
+! go test -run FuzzWrongType corpustesting/fuzz_testdata_corpus_test.go
+! stdout ^ok
+stdout FAIL
+
 -- noop_fuzz_test.go --
 package noop_fuzz
 
@@ -384,6 +389,10 @@ func FuzzInNestedDir(f *testing.F) {
     f.Fuzz(func(t *testing.T, b []byte) {})
 }
 
+func FuzzWrongType(f *testing.F) {
+    f.Fuzz(func(t *testing.T, b []byte) {})
+}
+
 -- corpustesting/testdata/corpus/FuzzFail/1 --
 go test fuzz v1
 []byte("12345")
@@ -394,4 +403,7 @@ go test fuzz v1
 malformed
 -- corpustesting/testdata/corpus/FuzzInNestedDir/anotherdir/1 --
 go test fuzz v1
-[]byte("12345")
\ No newline at end of file
+[]byte("12345")
+-- corpustesting/testdata/corpus/FuzzWrongType/1 --
+go test fuzz v1
+int("00000")
\ No newline at end of file
index 586b51188cbb84c7669d31254afa9425f0c04423..b9d2d4cd5fb06bccff08578a05259c903f3a810f 100644 (file)
@@ -506,21 +506,12 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) {
                if err != nil {
                        return nil, fmt.Errorf("failed to read corpus file: %v", err)
                }
-               vals, err := unmarshalCorpusFile(data)
+               var vals []interface{}
+               vals, err = readCorpusData(data, types)
                if err != nil {
-                       errs = append(errs, fmt.Errorf("failed to unmarshal %q: %v", filename, err))
-                       continue
-               }
-               if len(vals) != len(types) {
-                       errs = append(errs, fmt.Errorf("wrong number of values in corpus file %q: %d, want %d", filename, len(vals), len(types)))
+                       errs = append(errs, fmt.Errorf("%q: %v", filename, err))
                        continue
                }
-               for i := range types {
-                       if reflect.TypeOf(vals[i]) != types[i] {
-                               errs = append(errs, fmt.Errorf("mismatched types in corpus file %q: %v, want %v", filename, vals, types))
-                               continue
-                       }
-               }
                corpus = append(corpus, CorpusEntry{Name: file.Name(), Data: data, Values: vals})
        }
        if len(errs) > 0 {
@@ -529,6 +520,22 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) {
        return corpus, nil
 }
 
+func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) {
+       vals, err := unmarshalCorpusFile(data)
+       if err != nil {
+               return nil, fmt.Errorf("unmarshal: %v", err)
+       }
+       if len(vals) != len(types) {
+               return nil, fmt.Errorf("wrong number of values in corpus file: %d, want %d", len(vals), len(types))
+       }
+       for i := range types {
+               if reflect.TypeOf(vals[i]) != types[i] {
+                       return nil, fmt.Errorf("mismatched types in corpus file: %v, want %v", vals, types)
+               }
+       }
+       return vals, nil
+}
+
 // writeToCorpus atomically writes the given bytes to a new file in testdata.
 // If the directory does not exist, it will create one. If the file already
 // exists, writeToCorpus will not rewrite it. writeToCorpus returns the