Commit e1ee3140 authored by Dmitry Vyukov's avatar Dmitry Vyukov

internal/trace: fix fuzzer crashers

Fixes #11766
Fixes #11769
Fixes #11767
Fixes #11770

Change-Id: I441382af58f60deb46dcdd70076763b2c47738d4
Reviewed-on: https://go-review.googlesource.com/12378Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent c4bfd2de
...@@ -206,6 +206,11 @@ func parseEvents(rawEvents []rawEvent) (events []*Event, err error) { ...@@ -206,6 +206,11 @@ func parseEvents(rawEvents []rawEvent) (events []*Event, err error) {
raw.off, size) raw.off, size)
return 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] id := raw.args[0]
if id != 0 && size > 0 { if id != 0 && size > 0 {
stk := make([]*Frame, size) stk := make([]*Frame, size)
...@@ -245,6 +250,10 @@ func parseEvents(rawEvents []rawEvent) (events []*Event, err error) { ...@@ -245,6 +250,10 @@ func parseEvents(rawEvents []rawEvent) (events []*Event, err error) {
events = append(events, e) events = append(events, e)
} }
} }
if len(events) == 0 {
err = fmt.Errorf("trace is empty")
return
}
// Attach stack traces. // Attach stack traces.
for _, ev := range events { for _, ev := range events {
...@@ -361,7 +370,7 @@ func postProcessTrace(events []*Event) error { ...@@ -361,7 +370,7 @@ func postProcessTrace(events []*Event) error {
gs[0] = gdesc{state: gRunning} gs[0] = gdesc{state: gRunning}
var evGC *Event 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 name := EventDescriptions[ev.Type].Name
if g.state != gRunning { 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) 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 { ...@@ -369,6 +378,9 @@ func postProcessTrace(events []*Event) error {
if p.g != ev.G { 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) 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 return nil
} }
...@@ -438,7 +450,7 @@ func postProcessTrace(events []*Event) error { ...@@ -438,7 +450,7 @@ func postProcessTrace(events []*Event) error {
g1.state = gWaiting g1.state = gWaiting
gs[ev.Args[0]] = g1 gs[ev.Args[0]] = g1
case EvGoCreate: case EvGoCreate:
if err := checkRunning(p, g, ev); err != nil { if err := checkRunning(p, g, ev, true); err != nil {
return err return err
} }
if _, ok := gs[ev.Args[0]]; ok { if _, ok := gs[ev.Args[0]]; ok {
...@@ -466,7 +478,7 @@ func postProcessTrace(events []*Event) error { ...@@ -466,7 +478,7 @@ func postProcessTrace(events []*Event) error {
g.ev = nil g.ev = nil
} }
case EvGoEnd, EvGoStop: case EvGoEnd, EvGoStop:
if err := checkRunning(p, g, ev); err != nil { if err := checkRunning(p, g, ev, false); err != nil {
return err return err
} }
g.evStart.Link = ev g.evStart.Link = ev
...@@ -474,7 +486,7 @@ func postProcessTrace(events []*Event) error { ...@@ -474,7 +486,7 @@ func postProcessTrace(events []*Event) error {
g.state = gDead g.state = gDead
p.g = 0 p.g = 0
case EvGoSched, EvGoPreempt: case EvGoSched, EvGoPreempt:
if err := checkRunning(p, g, ev); err != nil { if err := checkRunning(p, g, ev, false); err != nil {
return err return err
} }
g.state = gRunnable g.state = gRunnable
...@@ -503,12 +515,12 @@ func postProcessTrace(events []*Event) error { ...@@ -503,12 +515,12 @@ func postProcessTrace(events []*Event) error {
g1.ev = ev g1.ev = ev
gs[ev.Args[0]] = g1 gs[ev.Args[0]] = g1
case EvGoSysCall: case EvGoSysCall:
if err := checkRunning(p, g, ev); err != nil { if err := checkRunning(p, g, ev, false); err != nil {
return err return err
} }
g.ev = ev g.ev = ev
case EvGoSysBlock: case EvGoSysBlock:
if err := checkRunning(p, g, ev); err != nil { if err := checkRunning(p, g, ev, false); err != nil {
return err return err
} }
g.state = gWaiting g.state = gWaiting
...@@ -526,7 +538,7 @@ func postProcessTrace(events []*Event) error { ...@@ -526,7 +538,7 @@ func postProcessTrace(events []*Event) error {
g.ev = ev g.ev = ev
case EvGoSleep, EvGoBlock, EvGoBlockSend, EvGoBlockRecv, case EvGoSleep, EvGoBlock, EvGoBlockSend, EvGoBlockRecv,
EvGoBlockSelect, EvGoBlockSync, EvGoBlockCond, EvGoBlockNet: EvGoBlockSelect, EvGoBlockSync, EvGoBlockCond, EvGoBlockNet:
if err := checkRunning(p, g, ev); err != nil { if err := checkRunning(p, g, ev, false); err != nil {
return err return err
} }
g.state = gWaiting g.state = gWaiting
......
// 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)
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment