Commit 944a0859 authored by Dmitry Vyukov's avatar Dmitry Vyukov

internal/trace: fix int overflow in timestamps

Fixes #15102

Change-Id: I7fdb6464afd0b7af9b6652051416f0fddd34dc9a
Reviewed-on: https://go-review.googlesource.com/21730Reviewed-by: 's avatarAustin Clements <austin@google.com>
parent b6cd6d7d
......@@ -372,8 +372,10 @@ func parseEvents(ver int, rawEvents []rawEvent, strings map[uint64]string) (even
return
}
minTs := events[0].Ts
// Use floating point to avoid integer overflows.
freq := 1e9 / float64(ticksPerSec)
for _, ev := range events {
ev.Ts = (ev.Ts - minTs) * 1e9 / ticksPerSec
ev.Ts = int64(float64(ev.Ts-minTs) * freq)
// Move timers and syscalls to separate fake Ps.
if timerGoid != 0 && ev.G == timerGoid && ev.Type == EvGoUnblock {
ev.P = TimerP
......
......@@ -85,3 +85,55 @@ func TestParseVersion(t *testing.T) {
}
}
}
func TestTimestampOverflow(t *testing.T) {
// Test that parser correctly handles large timestamps (long tracing).
w := newWriter()
w.emit(EvBatch, 0, 0, 0)
w.emit(EvFrequency, 1e9, 0)
for ts := uint64(1); ts < 1e16; ts *= 2 {
w.emit(EvGoCreate, 1, ts, ts, 1, 0)
}
if _, err := Parse(w, ""); err != nil {
t.Fatalf("failed to parse: %v", err)
}
}
type writer struct {
bytes.Buffer
}
func newWriter() *writer {
w := new(writer)
w.Write([]byte("go 1.7 trace\x00\x00\x00\x00"))
return w
}
func (w *writer) emit(typ byte, args ...uint64) {
nargs := byte(len(args)) - 2
if nargs > 3 {
nargs = 3
}
buf := []byte{typ | nargs<<6}
if nargs == 3 {
buf = append(buf, 0)
}
for _, a := range args {
buf = appendVarint(buf, a)
}
if nargs == 3 {
buf[1] = byte(len(buf) - 2)
}
n, err := w.Write(buf)
if n != len(buf) || err != nil {
panic("failed to write")
}
}
func appendVarint(buf []byte, v uint64) []byte {
for ; v >= 0x80; v >>= 7 {
buf = append(buf, 0x80|byte(v))
}
buf = append(buf, byte(v))
return buf
}
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