]> Cypherpunks repositories - gostls13.git/commitdiff
internal/trace: fix fuzzer crashers
authorDmitry Vyukov <dvyukov@google.com>
Sat, 18 Jul 2015 00:53:48 +0000 (17:53 -0700)
committerDmitry Vyukov <dvyukov@google.com>
Sat, 18 Jul 2015 19:51:50 +0000 (19:51 +0000)
Fixes #11766
Fixes #11769
Fixes #11767
Fixes #11770

Change-Id: I441382af58f60deb46dcdd70076763b2c47738d4
Reviewed-on: https://go-review.googlesource.com/12378
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/internal/trace/parser.go
src/internal/trace/parser_test.go [new file with mode: 0644]

index ece5bc188de51c27d8fbd6b5b1c2e4cfea7cfbfa..bfe6b7301545baf6d7e121c340f17a5ab914439b 100644 (file)
@@ -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 (file)
index 0000000..7d066e8
--- /dev/null
@@ -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)
+               }
+       }
+}