From e1ee31400a4258985647a6d699c7df56a81d7a98 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 17 Jul 2015 17:53:48 -0700 Subject: [PATCH] internal/trace: fix fuzzer crashers Fixes #11766 Fixes #11769 Fixes #11767 Fixes #11770 Change-Id: I441382af58f60deb46dcdd70076763b2c47738d4 Reviewed-on: https://go-review.googlesource.com/12378 Reviewed-by: Brad Fitzpatrick Run-TryBot: Dmitry Vyukov TryBot-Result: Gobot Gobot --- src/internal/trace/parser.go | 26 +++++++++++++++++++------- src/internal/trace/parser_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 src/internal/trace/parser_test.go diff --git a/src/internal/trace/parser.go b/src/internal/trace/parser.go index ece5bc188de51c..bfe6b7301545ba 100644 --- a/src/internal/trace/parser.go +++ b/src/internal/trace/parser.go @@ -206,6 +206,11 @@ func parseEvents(rawEvents []rawEvent) (events []*Event, err error) { raw.off, size) return } + if uint64(len(raw.args)) != size+2 { + err = fmt.Errorf("EvStack has wrong number of arguments at offset 0x%x: want %v, got %v", + raw.off, size+2, len(raw.args)) + return + } id := raw.args[0] if id != 0 && size > 0 { stk := make([]*Frame, size) @@ -245,6 +250,10 @@ func parseEvents(rawEvents []rawEvent) (events []*Event, err error) { events = append(events, e) } } + if len(events) == 0 { + err = fmt.Errorf("trace is empty") + return + } // Attach stack traces. for _, ev := range events { @@ -361,7 +370,7 @@ func postProcessTrace(events []*Event) error { gs[0] = gdesc{state: gRunning} var evGC *Event - checkRunning := func(p pdesc, g gdesc, ev *Event) error { + checkRunning := func(p pdesc, g gdesc, ev *Event, allowG0 bool) error { name := EventDescriptions[ev.Type].Name if g.state != gRunning { return fmt.Errorf("g %v is not running while %v (offset %v, time %v)", ev.G, name, ev.Off, ev.Ts) @@ -369,6 +378,9 @@ func postProcessTrace(events []*Event) error { if p.g != ev.G { return fmt.Errorf("p %v is not running g %v while %v (offset %v, time %v)", ev.P, ev.G, name, ev.Off, ev.Ts) } + if !allowG0 && ev.G == 0 { + return fmt.Errorf("g 0 did %v (offset %v, time %v)", EventDescriptions[ev.Type].Name, ev.Off, ev.Ts) + } return nil } @@ -438,7 +450,7 @@ func postProcessTrace(events []*Event) error { g1.state = gWaiting gs[ev.Args[0]] = g1 case EvGoCreate: - if err := checkRunning(p, g, ev); err != nil { + if err := checkRunning(p, g, ev, true); err != nil { return err } if _, ok := gs[ev.Args[0]]; ok { @@ -466,7 +478,7 @@ func postProcessTrace(events []*Event) error { g.ev = nil } case EvGoEnd, EvGoStop: - if err := checkRunning(p, g, ev); err != nil { + if err := checkRunning(p, g, ev, false); err != nil { return err } g.evStart.Link = ev @@ -474,7 +486,7 @@ func postProcessTrace(events []*Event) error { g.state = gDead p.g = 0 case EvGoSched, EvGoPreempt: - if err := checkRunning(p, g, ev); err != nil { + if err := checkRunning(p, g, ev, false); err != nil { return err } g.state = gRunnable @@ -503,12 +515,12 @@ func postProcessTrace(events []*Event) error { g1.ev = ev gs[ev.Args[0]] = g1 case EvGoSysCall: - if err := checkRunning(p, g, ev); err != nil { + if err := checkRunning(p, g, ev, false); err != nil { return err } g.ev = ev case EvGoSysBlock: - if err := checkRunning(p, g, ev); err != nil { + if err := checkRunning(p, g, ev, false); err != nil { return err } g.state = gWaiting @@ -526,7 +538,7 @@ func postProcessTrace(events []*Event) error { g.ev = ev case EvGoSleep, EvGoBlock, EvGoBlockSend, EvGoBlockRecv, EvGoBlockSelect, EvGoBlockSync, EvGoBlockCond, EvGoBlockNet: - if err := checkRunning(p, g, ev); err != nil { + if err := checkRunning(p, g, ev, false); err != nil { return err } g.state = gWaiting diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go new file mode 100644 index 00000000000000..7d066e86fe1cd2 --- /dev/null +++ b/src/internal/trace/parser_test.go @@ -0,0 +1,26 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package trace + +import ( + "strings" + "testing" +) + +func TestCorruptedInputs(t *testing.T) { + // These inputs crashed parser previously. + tests := []string{ + "gotrace\x00\x020", + "gotrace\x00Q00\x020", + "gotrace\x00T00\x020", + "gotrace\x00\xc3\x0200", + } + for _, data := range tests { + events, err := Parse(strings.NewReader(data)) + if err == nil || events != nil { + t.Fatalf("no error on input: %q\n", t) + } + } +}