aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-09-27 12:50:25 +0200
committerDmitry Vyukov <dvyukov@google.com>2018-09-27 12:50:25 +0200
commit98b28ead6ceaf22064b9715cc1950848d2bdef0b (patch)
tree067aea7eda2c79e553351917fe1d48f814f9326e /pkg
parent58fca249ef46c67eeb8e5f495bd3c289d19974f8 (diff)
pkg/report: fix few fuzz bugs
Improve go-fuzz fuzzer function and fix few new bugs it finds: 1. Panic in linux parser (bad). 2. Akaros can report empty rep.Report. 3. Fuchsia can return empty rep.Report.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/report/akaros.go11
-rw-r--r--pkg/report/fuchsia.go4
-rw-r--r--pkg/report/fuzz.go80
-rw-r--r--pkg/report/linux.go3
-rw-r--r--pkg/report/report.go6
-rw-r--r--pkg/report/report_test.go10
6 files changed, 83 insertions, 31 deletions
diff --git a/pkg/report/akaros.go b/pkg/report/akaros.go
index 6e6e51bc9..44fff60ee 100644
--- a/pkg/report/akaros.go
+++ b/pkg/report/akaros.go
@@ -23,7 +23,9 @@ type akaros struct {
func ctorAkaros(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) {
ctx := &akaros{
ignores: ignores,
- objfile: filepath.Join(kernelObj, "akaros-kernel-64b"),
+ }
+ if kernelObj != "" {
+ ctx.objfile = filepath.Join(kernelObj, "akaros-kernel-64b")
}
return ctx, nil, nil
}
@@ -37,11 +39,16 @@ func (ctx *akaros) Parse(output []byte) *Report {
if rep == nil {
return nil
}
- rep.Report = ctx.minimizeReport(rep.Report)
+ if report := ctx.minimizeReport(rep.Report); len(report) != 0 {
+ rep.Report = report
+ }
return rep
}
func (ctx *akaros) Symbolize(rep *Report) error {
+ if ctx.objfile == "" {
+ return nil
+ }
symb := symbolizer.NewSymbolizer()
defer symb.Close()
var symbolized []byte
diff --git a/pkg/report/fuchsia.go b/pkg/report/fuchsia.go
index a4c4de460..e034f3de7 100644
--- a/pkg/report/fuchsia.go
+++ b/pkg/report/fuchsia.go
@@ -63,7 +63,9 @@ func (ctx *fuchsia) Parse(output []byte) *Report {
return nil
}
rep.Output = output
- rep.Report = ctx.shortenReport(rep.Report)
+ if report := ctx.shortenReport(rep.Report); len(report) != 0 {
+ rep.Report = report
+ }
return rep
}
diff --git a/pkg/report/fuzz.go b/pkg/report/fuzz.go
index b7f5ef2a5..8527c079b 100644
--- a/pkg/report/fuzz.go
+++ b/pkg/report/fuzz.go
@@ -1,36 +1,64 @@
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-// +build gofuzz
-
package report
import (
- "regexp"
-)
+ "fmt"
-var reporter, _ = NewReporter("linux", "", "", nil, []*regexp.Regexp{regexp.MustCompile("foo")})
+ "github.com/google/syzkaller/pkg/mgrconfig"
+)
-func FuzzLinux(data []byte) int {
- containsCrash := reporter.ContainsCrash(data)
- rep := reporter.Parse(data)
- if containsCrash != (rep != nil) {
- panic("ContainsCrash and Parse disagree")
- }
- if rep == nil {
- return 0
- }
- if rep.Title == "" {
- panic("rep.Title == \"\"")
+func Fuzz(data []byte) int {
+ res := 0
+ for _, reporter := range fuzzReporters {
+ typ := reporter.(*reporterWrapper).typ
+ containsCrash := reporter.ContainsCrash(data)
+ rep := reporter.Parse(data)
+ if containsCrash != (rep != nil) {
+ panic(fmt.Sprintf("%v: ContainsCrash and Parse disagree", typ))
+ }
+ if rep == nil {
+ continue
+ }
+ res = 1
+ reporter.Symbolize(rep)
+ if rep.Title == "" {
+ panic(fmt.Sprintf("%v: Title is empty", typ))
+ }
+ if len(rep.Report) == 0 {
+ panic(fmt.Sprintf("%v: len(Report) == 0", typ))
+ }
+ if len(rep.Output) == 0 {
+ panic(fmt.Sprintf("%v: len(Output) == 0", typ))
+ }
+ if rep.StartPos != 0 && rep.EndPos != 0 && rep.StartPos >= rep.EndPos {
+ panic(fmt.Sprintf("%v: StartPos=%v >= EndPos=%v", typ, rep.StartPos, rep.EndPos))
+ }
+ if rep.EndPos > len(rep.Output) {
+ panic(fmt.Sprintf("%v: EndPos=%v > len(Output)=%v", typ, rep.EndPos, len(rep.Output)))
+ }
}
- if len(rep.Report) == 0 {
- panic("len(rep.Report) == 0")
- }
- if len(rep.Output) == 0 {
- panic("len(rep.Output) == 0")
- }
- if rep.StartPos >= rep.EndPos {
- panic("rep.StartPos >= rep.EndPos")
- }
- return 1
+ return res
}
+
+var fuzzReporters = func() []Reporter {
+ var reporters []Reporter
+ for os := range ctors {
+ if os == "windows" {
+ continue
+ }
+ cfg := &mgrconfig.Config{
+ TargetOS: os,
+ }
+ reporter, err := NewReporter(cfg)
+ if err != nil {
+ panic(err)
+ }
+ if _, ok := reporter.(*stub); ok {
+ continue
+ }
+ reporters = append(reporters, reporter)
+ }
+ return reporters
+}()
diff --git a/pkg/report/linux.go b/pkg/report/linux.go
index 1880298b6..97d5e84c3 100644
--- a/pkg/report/linux.go
+++ b/pkg/report/linux.go
@@ -156,6 +156,7 @@ func (ctx *linux) Parse(output []byte) *Report {
rep.Report = append(rep.Report, prefix...)
rep.Report = append(rep.Report, '\n')
}
+ rep.reportPrefixLen = len(rep.Report)
rep.Report = append(rep.Report, report...)
if !rep.Corrupted {
rep.Corrupted, rep.CorruptedReason = ctx.isCorrupted(title, report, format)
@@ -377,7 +378,7 @@ func symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, err
}
func (ctx *linux) extractGuiltyFile(rep *Report) string {
- report := rep.Report[rep.StartPos:]
+ report := rep.Report[rep.reportPrefixLen:]
if linuxRcuStall.Match(report) {
// Special case for rcu stalls.
// There are too many frames that we want to skip before actual guilty frames,
diff --git a/pkg/report/report.go b/pkg/report/report.go
index e97930fe0..89322a6f4 100644
--- a/pkg/report/report.go
+++ b/pkg/report/report.go
@@ -47,6 +47,8 @@ type Report struct {
Maintainers []string
// guiltyFile is the source file that we think is to blame for the crash (filled in by Symbolize).
guiltyFile string
+ // reportPrefixLen is length of additional prefix lines that we added before actual crash report.
+ reportPrefixLen int
}
// NewReporter creates reporter for the specified OS/Type.
@@ -71,7 +73,7 @@ func NewReporter(cfg *mgrconfig.Config) (Reporter, error) {
if err != nil {
return nil, err
}
- return &reporterWrapper{rep, supps}, nil
+ return &reporterWrapper{rep, supps, typ}, nil
}
var ctors = map[string]fn{
@@ -102,6 +104,7 @@ func compileRegexps(list []string) ([]*regexp.Regexp, error) {
type reporterWrapper struct {
Reporter
suppressions []*regexp.Regexp
+ typ string
}
func (wrap *reporterWrapper) Parse(output []byte) *Report {
@@ -450,6 +453,7 @@ func simpleLineParser(output []byte, oopses []*oops, params *stackParams, ignore
if match != -1 {
oops = oops1
rep.StartPos = pos
+ rep.EndPos = next
break
}
}
diff --git a/pkg/report/report_test.go b/pkg/report/report_test.go
index 2eaf54fa6..6b83d2104 100644
--- a/pkg/report/report_test.go
+++ b/pkg/report/report_test.go
@@ -302,3 +302,13 @@ func TestReplace(t *testing.T) {
})
}
}
+
+func TestFuzz(t *testing.T) {
+ for _, data := range []string{
+ "kernel panicType 'help' for a list of commands",
+ "0000000000000000000\n\n\n\n\n\nBooting the kernel.",
+ "ZIRCON KERNEL PANICHalted",
+ } {
+ Fuzz([]byte(data))
+ }
+}