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)
events = append(events, e)
}
}
+ if len(events) == 0 {
+ err = fmt.Errorf("trace is empty")
+ return
+ }
// Attach stack traces.
for _, ev := range events {
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)
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
}
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 {
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
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
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
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
--- /dev/null
+// 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)
+ }
+ }
+}