Kaynağa Gözat

Added files to enable fuzz testing and fixed bug found with fuzzing (#150)

* Added files to enable fuzz testing
* Added test for crashes found with fuzzing
* fixed divide-by-zero error in profile/legacy_java_profile.go found with fuzzing
Margaret Nolan 7 yıl önce
ebeveyn
işleme
42b93caf0e

+ 37
- 0
fuzz/README.md Dosyayı Görüntüle

@@ -0,0 +1,37 @@
1
+This is an explanation of how to do fuzzing of ParseData. This uses github.com/dvyukov/go-fuzz/ for fuzzing.
2
+
3
+# How to use
4
+First, get go-fuzz 
5
+```
6
+$ go get github.com/dvyukov/go-fuzz/go-fuzz
7
+$ go get github.com/dvyukov/go-fuzz/go-fuzz-build
8
+```
9
+
10
+Build the test program by calling the following command 
11
+(assuming you have files for pprof located in github.com/google/pprof within go's src folder)
12
+
13
+```
14
+$ go-fuzz-build github.com/google/pprof/fuzz
15
+```
16
+The above command will produce pprof-fuzz.zip 
17
+
18
+
19
+Now you can run the fuzzer by calling
20
+
21
+```
22
+$ go-fuzz -bin=./pprof-fuzz.zip -workdir=fuzz
23
+```
24
+
25
+This will save a corpus of files used by the fuzzer in ./fuzz/corpus, and
26
+all files that caused ParseData to crash in ./fuzz/crashers.
27
+
28
+For more details on the usage, see github.com/dvyukov/go-fuzz/
29
+
30
+# About the to corpus
31
+
32
+Right now, fuzz/corpus contains the corpus initially given to the fuzzer
33
+
34
+If using the above commands, fuzz/corpus will be used to generate the initial corpus during fuzz testing.
35
+
36
+One can add profiles into the corpus by placing these files in the corpus directory (fuzz/corpus)
37
+prior to calling go-fuzz-build.

+ 0
- 0
fuzz/corpus/empty Dosyayı Görüntüle


+ 24
- 0
fuzz/fuzz_test.go Dosyayı Görüntüle

@@ -0,0 +1,24 @@
1
+package pprof
2
+
3
+import (
4
+	"github.com/google/pprof/profile"
5
+	"io/ioutil"
6
+	"testing"
7
+)
8
+
9
+func TestParseData(t *testing.T) {
10
+	const path = "testdata/"
11
+	files, err := ioutil.ReadDir(path)
12
+	if err != nil {
13
+		t.Errorf("Problem reading directory %s : %v", path, err)
14
+	}
15
+	for _, f := range files {
16
+		file := path + f.Name()
17
+		inbytes, err := ioutil.ReadFile(file)
18
+		if err != nil {
19
+			t.Errorf("Problem reading file: %s : %v", file, err)
20
+			continue
21
+		}
22
+		profile.ParseData(inbytes)
23
+	}
24
+}

+ 11
- 0
fuzz/main.go Dosyayı Görüntüle

@@ -0,0 +1,11 @@
1
+package pprof
2
+
3
+import (
4
+	"github.com/google/pprof/profile"
5
+)
6
+
7
+// Fuzz can be used with https://github.com/dvyukov/go-fuzz to do fuzz testing on ParseData
8
+func Fuzz(data []byte) int {
9
+	profile.ParseData(data)
10
+	return 0
11
+}

+ 2
- 0
fuzz/testdata/7e3c92482f6f39fc502b822ded792c589849cca8 Dosyayı Görüntüle

@@ -0,0 +1,2 @@
1
+--- heapz 1 ---
2
+0 0 @ 0

+ 3
- 0
profile/legacy_java_profile.go Dosyayı Görüntüle

@@ -212,6 +212,9 @@ func parseJavaSamples(pType string, b []byte, p *Profile) ([]byte, map[uint64]*L
212 212
 			switch pType {
213 213
 			case "heap":
214 214
 				const javaHeapzSamplingRate = 524288 // 512K
215
+				if s.Value[0] == 0 {
216
+					return nil, nil, fmt.Errorf("parsing sample %s: second value must be non-zero", line)
217
+				}
215 218
 				s.NumLabel = map[string][]int64{"bytes": {s.Value[1] / s.Value[0]}}
216 219
 				s.Value[0], s.Value[1] = scaleHeapSample(s.Value[0], s.Value[1], javaHeapzSamplingRate)
217 220
 			case "contention":