diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-09-27 12:50:25 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-09-27 12:50:25 +0200 |
| commit | 98b28ead6ceaf22064b9715cc1950848d2bdef0b (patch) | |
| tree | 067aea7eda2c79e553351917fe1d48f814f9326e /pkg | |
| parent | 58fca249ef46c67eeb8e5f495bd3c289d19974f8 (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.go | 11 | ||||
| -rw-r--r-- | pkg/report/fuchsia.go | 4 | ||||
| -rw-r--r-- | pkg/report/fuzz.go | 80 | ||||
| -rw-r--r-- | pkg/report/linux.go | 3 | ||||
| -rw-r--r-- | pkg/report/report.go | 6 | ||||
| -rw-r--r-- | pkg/report/report_test.go | 10 |
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)) + } +} |
