diff --git a/trace/base.go b/trace/base.go index 2c4db2fd..86585b1b 100644 --- a/trace/base.go +++ b/trace/base.go @@ -13,6 +13,7 @@ package trace import ( "fmt" + "math" "strings" "golang.org/x/exp/trace/internal/event" @@ -48,6 +49,7 @@ type evTable struct { freq frequency strings dataTable[stringID, string] stacks dataTable[stackID, stack] + pcs map[uint64]frame // extraStrings are strings that get generated during // parsing but haven't come directly from the trace, so @@ -127,8 +129,12 @@ func (d *dataTable[EI, E]) compactify() { minID = id } } + if maxID >= math.MaxInt { + // We can't create a slice big enough to hold maxID elements + return + } // We're willing to waste at most 2x memory. - if int(maxID-minID) > 2*len(d.sparse) { + if int(maxID-minID) > max(len(d.sparse), 2*len(d.sparse)) { return } if int(minID) > len(d.sparse) { @@ -150,7 +156,7 @@ func (d *dataTable[EI, E]) get(id EI) (E, bool) { if id == 0 { return *new(E), true } - if int(id) < len(d.dense) { + if uint64(id) < uint64(len(d.dense)) { if d.present[id/8]&(uint8(1)<<(id%8)) != 0 { return d.dense[id], true } @@ -240,12 +246,12 @@ func (s cpuSample) asEvent(table *evTable) Event { // stack represents a goroutine stack sample. type stack struct { - frames []frame + pcs []uint64 } func (s stack) String() string { var sb strings.Builder - for _, frame := range s.frames { + for _, frame := range s.pcs { fmt.Fprintf(&sb, "\t%#v\n", frame) } return sb.String() diff --git a/trace/batch.go b/trace/batch.go index 9fafac99..0bde22d2 100644 --- a/trace/batch.go +++ b/trace/batch.go @@ -9,7 +9,6 @@ package trace import ( - "bufio" "bytes" "encoding/binary" "fmt" @@ -47,7 +46,10 @@ func (b *batch) isFreqBatch() bool { } // readBatch reads the next full batch from r. -func readBatch(r *bufio.Reader) (batch, uint64, error) { +func readBatch(r interface { + io.Reader + io.ByteReader +}) (batch, uint64, error) { // Read batch header byte. b, err := r.ReadByte() if err != nil { diff --git a/trace/batchcursor.go b/trace/batchcursor.go index f8fc3fdb..95824689 100644 --- a/trace/batchcursor.go +++ b/trace/batchcursor.go @@ -72,7 +72,7 @@ func readTimedBaseEvent(b []byte, e *baseEvent) (int, timestamp, error) { // Get the event type. typ := event.Type(b[0]) specs := go122.Specs() - if int(typ) > len(specs) { + if int(typ) >= len(specs) { return 0, 0, fmt.Errorf("found invalid event type: %v", typ) } e.typ = typ @@ -86,11 +86,17 @@ func readTimedBaseEvent(b []byte, e *baseEvent) (int, timestamp, error) { // Read timestamp diff. ts, nb := binary.Uvarint(b[n:]) + if nb <= 0 { + return 0, 0, fmt.Errorf("found invalid uvarint for timestamp") + } n += nb // Read the rest of the arguments. for i := 0; i < len(spec.Args)-1; i++ { arg, nb := binary.Uvarint(b[n:]) + if nb <= 0 { + return 0, 0, fmt.Errorf("found invalid uvarint") + } e.args[i] = arg n += nb } diff --git a/trace/event.go b/trace/event.go index a9d59474..a73e624e 100644 --- a/trace/event.go +++ b/trace/event.go @@ -268,7 +268,8 @@ func (s Stack) Frames(yield func(f StackFrame) bool) bool { return true } stk := s.table.stacks.mustGet(s.id) - for _, f := range stk.frames { + for _, pc := range stk.pcs { + f := s.table.pcs[pc] sf := StackFrame{ PC: f.pc, Func: s.table.strings.mustGet(f.funcID), diff --git a/trace/generation.go b/trace/generation.go index 9364b436..28ec7732 100644 --- a/trace/generation.go +++ b/trace/generation.go @@ -47,7 +47,9 @@ type spilledBatch struct { // batch read of the next generation, if any. func readGeneration(r *bufio.Reader, spill *spilledBatch) (*generation, *spilledBatch, error) { g := &generation{ - evTable: new(evTable), + evTable: &evTable{ + pcs: make(map[uint64]frame), + }, batches: make(map[ThreadID][]batch), } // Process the spilled batch. @@ -110,7 +112,7 @@ func readGeneration(r *bufio.Reader, spill *spilledBatch) (*generation, *spilled g.strings.compactify() // Validate stacks. - if err := validateStackStrings(&g.stacks, &g.strings); err != nil { + if err := validateStackStrings(&g.stacks, &g.strings, g.pcs); err != nil { return nil, nil, err } @@ -134,7 +136,7 @@ func processBatch(g *generation, b batch) error { return err } case b.isStacksBatch(): - if err := addStacks(&g.stacks, b); err != nil { + if err := addStacks(&g.stacks, g.pcs, b); err != nil { return err } case b.isCPUSamplesBatch(): @@ -160,11 +162,20 @@ func processBatch(g *generation, b batch) error { // validateStackStrings makes sure all the string references in // the stack table are present in the string table. -func validateStackStrings(stacks *dataTable[stackID, stack], strings *dataTable[stringID, string]) error { +func validateStackStrings( + stacks *dataTable[stackID, stack], + strings *dataTable[stringID, string], + frames map[uint64]frame, +) error { var err error stacks.forEach(func(id stackID, stk stack) bool { - for _, frame := range stk.frames { - _, ok := strings.get(frame.funcID) + for _, pc := range stk.pcs { + frame, ok := frames[pc] + if !ok { + err = fmt.Errorf("found unknown pc %x for stack %d", pc, id) + return false + } + _, ok = strings.get(frame.funcID) if !ok { err = fmt.Errorf("found invalid func string ID %d for stack %d", frame.funcID, id) return false @@ -241,7 +252,7 @@ func addStrings(stringTable *dataTable[stringID, string], b batch) error { // addStacks takes a batch whose first byte is an EvStacks event // (indicating that the batch contains only stacks) and adds each // string contained therein to the provided stacks map. -func addStacks(stackTable *dataTable[stackID, stack], b batch) error { +func addStacks(stackTable *dataTable[stackID, stack], pcs map[uint64]frame, b batch) error { if !b.isStacksBatch() { return fmt.Errorf("internal error: addStacks called on non-stacks batch") } @@ -277,7 +288,7 @@ func addStacks(stackTable *dataTable[stackID, stack], b batch) error { } // Each frame consists of 4 fields: pc, funcID (string), fileID (string), line. - frames := make([]frame, 0, nFrames) + frames := make([]uint64, 0, nFrames) for i := uint64(0); i < nFrames; i++ { // Read the frame data. pc, err := binary.ReadUvarint(r) @@ -296,16 +307,20 @@ func addStacks(stackTable *dataTable[stackID, stack], b batch) error { if err != nil { return fmt.Errorf("reading frame %d's line for stack %d: %w", i+1, id, err) } - frames = append(frames, frame{ - pc: pc, - funcID: stringID(funcID), - fileID: stringID(fileID), - line: line, - }) + frames = append(frames, pc) + + if _, ok := pcs[pc]; !ok { + pcs[pc] = frame{ + pc: pc, + funcID: stringID(funcID), + fileID: stringID(fileID), + line: line, + } + } } // Add the stack to the map. - if err := stackTable.insert(stackID(id), stack{frames: frames}); err != nil { + if err := stackTable.insert(stackID(id), stack{pcs: frames}); err != nil { return err } } diff --git a/trace/order.go b/trace/order.go index c89e5da8..e0f77c65 100644 --- a/trace/order.go +++ b/trace/order.go @@ -96,6 +96,9 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) case go122.EvProcStatus: pid := ProcID(ev.args[0]) status := go122.ProcStatus(ev.args[1]) + if int(status) >= len(go122ProcStatus2ProcState) { + return curCtx, false, fmt.Errorf("invalid status for proc %d: %d", pid, status) + } oldState := go122ProcStatus2ProcState[status] if s, ok := o.pStates[pid]; ok { if status == go122.ProcSyscallAbandoned && s.status == go122.ProcSyscall { @@ -272,6 +275,10 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) gid := GoID(ev.args[0]) mid := ThreadID(ev.args[1]) status := go122.GoStatus(ev.args[2]) + + if int(status) >= len(go122GoStatus2GoState) { + return curCtx, false, fmt.Errorf("invalid status for goroutine %d: %d", gid, status) + } oldState := go122GoStatus2GoState[status] if s, ok := o.gStates[gid]; ok { if s.status != status { @@ -299,6 +306,13 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) // Otherwise, we're talking about a G sitting in a syscall on an M. // Validate the named M. if mid == curCtx.M { + if gen != o.initialGen && curCtx.G != gid { + // If this isn't the first generation, we *must* have seen this + // binding occur already. Even if the G was blocked in a syscall + // for multiple generations since trace start, we would have seen + // a previous GoStatus event that bound the goroutine to an M. + return curCtx, false, fmt.Errorf("inconsistent thread for syscalling goroutine %d: thread has goroutine %d", gid, curCtx.G) + } newCtx.G = gid break } @@ -646,7 +660,11 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) if !ok { return curCtx, false, fmt.Errorf("invalid string ID %v for %v event", nameID, typ) } - if err := o.gStates[curCtx.G].beginRegion(userRegion{tid, name}); err != nil { + gState, ok := o.gStates[curCtx.G] + if !ok { + return curCtx, false, fmt.Errorf("encountered EvUserRegionBegin without known state for current goroutine %d", curCtx.G) + } + if err := gState.beginRegion(userRegion{tid, name}); err != nil { return curCtx, false, err } return curCtx, true, nil @@ -660,7 +678,11 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) if !ok { return curCtx, false, fmt.Errorf("invalid string ID %v for %v event", nameID, typ) } - if err := o.gStates[curCtx.G].endRegion(userRegion{tid, name}); err != nil { + gState, ok := o.gStates[curCtx.G] + if !ok { + return curCtx, false, fmt.Errorf("encountered EvUserRegionEnd without known state for current goroutine %d", curCtx.G) + } + if err := gState.endRegion(userRegion{tid, name}); err != nil { return curCtx, false, err } return curCtx, true, nil @@ -762,7 +784,11 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) // ever reference curCtx.P. However, be lenient about this like we are with // GCMarkAssistActive; there's no reason the runtime couldn't change to block // in the middle of a sweep. - if err := o.pStates[pid].activeRange(makeRangeType(typ, 0), gen == o.initialGen); err != nil { + pState, ok := o.pStates[pid] + if !ok { + return curCtx, false, fmt.Errorf("encountered GCSweepActive for unknown proc %d", pid) + } + if err := pState.activeRange(makeRangeType(typ, 0), gen == o.initialGen); err != nil { return curCtx, false, err } return curCtx, true, nil @@ -785,7 +811,11 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) if typ == go122.EvSTWBegin { desc = stringID(ev.args[0]) } - if err := o.gStates[curCtx.G].beginRange(makeRangeType(typ, desc)); err != nil { + gState, ok := o.gStates[curCtx.G] + if !ok { + return curCtx, false, fmt.Errorf("encountered event of type %d without known state for current goroutine %d", typ, curCtx.G) + } + if err := gState.beginRange(makeRangeType(typ, desc)); err != nil { return curCtx, false, err } return curCtx, true, nil @@ -794,7 +824,11 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) // N.B. Like GoStatus, this can happen at any time, because it can // reference a non-running goroutine. Don't check anything about the // current scheduler context. - if err := o.gStates[gid].activeRange(makeRangeType(typ, 0), gen == o.initialGen); err != nil { + gState, ok := o.gStates[gid] + if !ok { + return curCtx, false, fmt.Errorf("uninitialized goroutine %d found during %s", gid, go122.EventString(typ)) + } + if err := gState.activeRange(makeRangeType(typ, 0), gen == o.initialGen); err != nil { return curCtx, false, err } return curCtx, true, nil @@ -802,7 +836,11 @@ func (o *ordering) advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) if err := validateCtx(curCtx, event.UserGoReqs); err != nil { return curCtx, false, err } - desc, err := o.gStates[curCtx.G].endRange(typ) + gState, ok := o.gStates[curCtx.G] + if !ok { + return curCtx, false, fmt.Errorf("encountered event of type %d without known state for current goroutine %d", typ, curCtx.G) + } + desc, err := gState.endRange(typ) if err != nil { return curCtx, false, err } @@ -921,6 +959,10 @@ func (s *gState) beginRegion(r userRegion) error { // endRegion ends a user region on the goroutine. func (s *gState) endRegion(r userRegion) error { + if len(s.regions) == 0 { + // We do not know about regions that began before tracing started. + return nil + } if next := s.regions[len(s.regions)-1]; next != r { return fmt.Errorf("misuse of region in goroutine %v: region end %v when the inner-most active region start event is %v", s.id, r, next) } diff --git a/trace/reader.go b/trace/reader.go index c561d58a..d7311c9b 100644 --- a/trace/reader.go +++ b/trace/reader.go @@ -161,6 +161,9 @@ func (r *Reader) ReadEvent() (e Event, err error) { } // Try to advance the head of the frontier, which should have the minimum timestamp. // This should be by far the most common case + if len(r.frontier) == 0 { + return Event{}, fmt.Errorf("broken trace: frontier is empty:\n[gen=%d]\n\n%s\n%s\n", r.gen.gen, dumpFrontier(r.frontier), dumpOrdering(&r.order)) + } bc := r.frontier[0] if ctx, ok, err := r.order.advance(&bc.ev, r.gen.evTable, bc.m, r.gen.gen); err != nil { return Event{}, err diff --git a/trace/reader_test.go b/trace/reader_test.go index 84d04a6d..401441c6 100644 --- a/trace/reader_test.go +++ b/trace/reader_test.go @@ -50,6 +50,53 @@ func TestReaderGolden(t *testing.T) { } } +func FuzzReader(f *testing.F) { + // Currently disabled because the parser doesn't do much validation and most + // getters can be made to panic. Turn this on once the parser is meant to + // reject invalid traces. + const testGetters = false + + f.Fuzz(func(t *testing.T, b []byte) { + r, err := trace.NewReader(bytes.NewReader(b)) + if err != nil { + return + } + for { + ev, err := r.ReadEvent() + if err != nil { + break + } + + if !testGetters { + continue + } + // Make sure getters don't do anything that panics + switch ev.Kind() { + case trace.EventLabel: + ev.Label() + case trace.EventLog: + ev.Log() + case trace.EventMetric: + ev.Metric() + case trace.EventRangeActive, trace.EventRangeBegin: + ev.Range() + case trace.EventRangeEnd: + ev.Range() + ev.RangeAttributes() + case trace.EventStateTransition: + ev.StateTransition() + case trace.EventRegionBegin, trace.EventRegionEnd: + ev.Region() + case trace.EventTaskBegin, trace.EventTaskEnd: + ev.Task() + case trace.EventSync: + case trace.EventStackSample: + case trace.EventBad: + } + } + }) +} + func testReader(t *testing.T, tr io.Reader, exp *testtrace.Expectation) { r, err := trace.NewReader(tr) if err != nil { diff --git a/trace/testdata/fuzz/FuzzReader/0cb1786dee0f090b b/trace/testdata/fuzz/FuzzReader/0cb1786dee0f090b new file mode 100644 index 00000000..326ebe1c --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/0cb1786dee0f090b @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x85\x00\x190000\x01\x0100\x88\x00\b0000000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/1e45307d5b2ec36d b/trace/testdata/fuzz/FuzzReader/1e45307d5b2ec36d new file mode 100644 index 00000000..406af9ca --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/1e45307d5b2ec36d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01000\x85\x00\b0001") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/2b05796f9b2fc48d b/trace/testdata/fuzz/FuzzReader/2b05796f9b2fc48d new file mode 100644 index 00000000..50fdccda --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/2b05796f9b2fc48d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x85\x00-0000\x01\x0100\x88\x00\b0000000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/2b9be9aebe08d511 b/trace/testdata/fuzz/FuzzReader/2b9be9aebe08d511 new file mode 100644 index 00000000..6bcb99ad --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/2b9be9aebe08d511 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x85\x00\x0f00\x120\x01\x0100\x88\x00\b0000000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/344331b314da0b08 b/trace/testdata/fuzz/FuzzReader/344331b314da0b08 new file mode 100644 index 00000000..de6e4694 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/344331b314da0b08 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x85\x00\b0000\x01\x01\xff00\xb8\x00\x1900\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x04\x1900\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x04\x1900\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x04\x1901\xff\xff\xff\xff\xff\xff\xff\xff0\x800") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/365d7b5b633b3f97 b/trace/testdata/fuzz/FuzzReader/365d7b5b633b3f97 new file mode 100644 index 00000000..8dc370f3 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/365d7b5b633b3f97 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x0100\x8c0\x85\x00\b0000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/4d9ddc909984e871 b/trace/testdata/fuzz/FuzzReader/4d9ddc909984e871 new file mode 100644 index 00000000..040b2a4c --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/4d9ddc909984e871 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x11\r\xa700\x01\x19000\x02$000000\x01\x0100\x05\b0000\x01\x0110\x11\r\xa700\x01\x19 00\x02\x110 0000") diff --git a/trace/testdata/fuzz/FuzzReader/56f073e57903588c b/trace/testdata/fuzz/FuzzReader/56f073e57903588c new file mode 100644 index 00000000..d34fe3f0 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/56f073e57903588c @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x85\x00\x1f0000\x01\x0100\x88\x00\b0000000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/9d6ee7d3ddf8d566 b/trace/testdata/fuzz/FuzzReader/9d6ee7d3ddf8d566 new file mode 100644 index 00000000..56772611 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/9d6ee7d3ddf8d566 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x11\r\xa700\x01\x19000\x02#000000\x01\x0100\x05\b0000\x01\x0110\x11\r\xa700\x01\x19 00\x02\x110 0000") diff --git a/trace/testdata/fuzz/FuzzReader/aeb749b6bc317b66 b/trace/testdata/fuzz/FuzzReader/aeb749b6bc317b66 new file mode 100644 index 00000000..f93b5a90 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/aeb749b6bc317b66 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01000\x85\x00\b0000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/closing-unknown-region b/trace/testdata/fuzz/FuzzReader/closing-unknown-region new file mode 100644 index 00000000..74332140 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/closing-unknown-region @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x87ߕ\xb4\x99\xb2\x06\x05\b\xa8ֹ\a\x01\x01\xf6\x9f\n\x9fÕ\xb4\x99\xb2\x06\x11\r\xa7\x02\x00\x01\x19\x05\x01\xf6\x9f\n\x02+\x04\x01\x00\x00") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/d478e18d2d6756b7 b/trace/testdata/fuzz/FuzzReader/d478e18d2d6756b7 new file mode 100644 index 00000000..3e5fda83 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/d478e18d2d6756b7 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x0100\x85\x00\"0000\x01\x0100\x88\x00\b0000000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/d91203cd397aa0bc b/trace/testdata/fuzz/FuzzReader/d91203cd397aa0bc new file mode 100644 index 00000000..d24b94ac --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/d91203cd397aa0bc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01001\x85\x00\b0000") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/invalid-proc-state b/trace/testdata/fuzz/FuzzReader/invalid-proc-state new file mode 100644 index 00000000..e5d32581 --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/invalid-proc-state @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x87ߕ\xb4\x99\xb2\x06\x05\b\xa8ֹ\a\x01\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x94镴\x99\xb2\x06\x05\r\xa7\x02\x00E") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/large-id b/trace/testdata/fuzz/FuzzReader/large-id new file mode 100644 index 00000000..0fb6273b --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/large-id @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x87ߕ\xb4\x99\xb2\x06\x05\b\xa8ֹ\a\x01\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x94镴\x99\xb2\x06\f\x02\x03\xff\xff\xff\xff\xff\xff\xff\x9f\x1d\x00") \ No newline at end of file diff --git a/trace/testdata/fuzz/FuzzReader/malformed-timestamp b/trace/testdata/fuzz/FuzzReader/malformed-timestamp new file mode 100644 index 00000000..850ca50f --- /dev/null +++ b/trace/testdata/fuzz/FuzzReader/malformed-timestamp @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("go 1.22 trace\x00\x00\x00\x01\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x87ߕ\xb4\x99\xb2\x06\x05\b\xa8ֹ\a\x01\x01\xfa\x9f\n\xa5ѕ\xb4\x99\xb2\x06\x0e\n\x97\x96\x96\x96\x96\x96\x96\x96\x96\x96\x01\x01\x01") diff --git a/trace/testdata/tests/go122-annotations-stress.test b/trace/testdata/tests/go122-annotations-stress.test index fe3c84b1..8da8c0f3 100644 --- a/trace/testdata/tests/go122-annotations-stress.test +++ b/trace/testdata/tests/go122-annotations-stress.test @@ -896,7 +896,7 @@ String id=18 String id=19 data="sleep" String id=20 - data="runtime.GoSched" + data="runtime.Gosched" String id=21 data="start trace" String id=22 diff --git a/trace/testdata/tests/go122-annotations.test b/trace/testdata/tests/go122-annotations.test index 4749d820..e4686734 100644 --- a/trace/testdata/tests/go122-annotations.test +++ b/trace/testdata/tests/go122-annotations.test @@ -220,7 +220,7 @@ String id=18 String id=19 data="sleep" String id=20 - data="runtime.GoSched" + data="runtime.Gosched" String id=21 data="start trace" String id=22 diff --git a/trace/testdata/tests/go122-gc-stress.test b/trace/testdata/tests/go122-gc-stress.test index 8d77fe14..d5e7266f 100644 --- a/trace/testdata/tests/go122-gc-stress.test +++ b/trace/testdata/tests/go122-gc-stress.test @@ -4086,7 +4086,7 @@ String id=18 String id=19 data="sleep" String id=20 - data="runtime.GoSched" + data="runtime.Gosched" String id=21 data="GC mark termination" String id=22