diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2024-04-15 17:21:00 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-04-15 15:31:30 +0000 |
| commit | 68d19d39aa87674e355a2c26333a0a4d4d370018 (patch) | |
| tree | 4c26e883dd7e2fc3347b0fb5baa70dd122409478 /pkg/report | |
| parent | be2d01ee635103a77a9f68576c852f5ef3b16d0f (diff) | |
pkg/report: remove unnecessary NewScan() calls
These are susceptible to potentially very long lines in the input.
Direct splitting by \n is more reliable.
Diffstat (limited to 'pkg/report')
| -rw-r--r-- | pkg/report/bsd.go | 7 | ||||
| -rw-r--r-- | pkg/report/fuchsia.go | 23 | ||||
| -rw-r--r-- | pkg/report/linux.go | 35 | ||||
| -rw-r--r-- | pkg/report/report.go | 17 |
4 files changed, 45 insertions, 37 deletions
diff --git a/pkg/report/bsd.go b/pkg/report/bsd.go index b627ed4f4..75cfa3426 100644 --- a/pkg/report/bsd.go +++ b/pkg/report/bsd.go @@ -4,7 +4,6 @@ package report import ( - "bufio" "bytes" "fmt" "path/filepath" @@ -57,11 +56,9 @@ func (ctx *bsd) Symbolize(rep *Report) error { symb := symbolizer.NewSymbolizer(ctx.config.target) defer symb.Close() var symbolized []byte - s := bufio.NewScanner(bytes.NewReader(rep.Report)) prefix := rep.reportPrefixLen - for s.Scan() { - line := append([]byte{}, s.Bytes()...) - line = append(line, '\n') + for _, line := range bytes.SplitAfter(rep.Report, []byte("\n")) { + line := bytes.Clone(line) newLine := ctx.symbolizeLine(symb.Symbolize, line) if prefix > len(symbolized) { prefix += len(newLine) - len(line) diff --git a/pkg/report/fuchsia.go b/pkg/report/fuchsia.go index 7f3461061..c4cd602e9 100644 --- a/pkg/report/fuchsia.go +++ b/pkg/report/fuchsia.go @@ -4,7 +4,6 @@ package report import ( - "bufio" "bytes" "fmt" "path/filepath" @@ -97,8 +96,7 @@ func (ctx *fuchsia) shortenStarnixPanicReport(report []byte, maxUnrelatedLines, out := new(bytes.Buffer) unrelatedLines := 0 unmatchedLines := 0 - for s := bufio.NewScanner(bytes.NewReader(report)); s.Scan(); { - line := s.Bytes() + for _, line := range lines(report) { if matchesAny(line, starnixFramePatterns) { unrelatedLines = 0 unmatchedLines = 0 @@ -113,16 +111,16 @@ func (ctx *fuchsia) shortenStarnixPanicReport(report []byte, maxUnrelatedLines, out.Write(line) out.WriteByte('\n') if unmatchedLines == maxUnmatchedLines { - return out.Bytes() + break } } - return out.Bytes() + return append(bytes.TrimRight(out.Bytes(), "\n"), '\n') } func (ctx *fuchsia) shortenReport(report []byte) []byte { out := new(bytes.Buffer) - for s := bufio.NewScanner(bytes.NewReader(report)); s.Scan(); { - line := zirconLinePrefix.ReplaceAll(s.Bytes(), nil) + for _, rawLine := range lines(report) { + line := zirconLinePrefix.ReplaceAll(rawLine, nil) if matchesAny(line, zirconUnrelated) { continue } @@ -139,14 +137,17 @@ func (ctx *fuchsia) symbolize(output []byte) []byte { symb := symbolizer.NewSymbolizer(ctx.config.target) defer symb.Close() out := new(bytes.Buffer) - for s := bufio.NewScanner(bytes.NewReader(output)); s.Scan(); { - line := s.Bytes() + + lines := lines(output) + for i := 0; i < len(lines); i++ { + line := lines[i] if bytes.Contains(line, zirconAssertFailed) && len(line) == 127 { // This is super hacky: but zircon splits the most important information in long assert lines // (and they are always long) into several lines in irreversible way. Try to restore full line. line = append([]byte{}, line...) - if s.Scan() { - line = append(line, s.Bytes()...) + if i+1 < len(lines) { + line = append(bytes.Clone(line), lines[i+1]...) + i++ } } if ctx.obj != "" { diff --git a/pkg/report/linux.go b/pkg/report/linux.go index 0fdcee54c..05f41676b 100644 --- a/pkg/report/linux.go +++ b/pkg/report/linux.go @@ -4,7 +4,6 @@ package report import ( - "bufio" "bytes" "encoding/binary" "fmt" @@ -404,8 +403,8 @@ func (ctx *linux) symbolize(rep *Report) error { } var symbolized []byte prefix := rep.reportPrefixLen - for _, originalLine := range bytes.SplitAfter(rep.Report, []byte("\n")) { - line := append([]byte{}, originalLine...) + for _, line := range bytes.SplitAfter(rep.Report, []byte("\n")) { + line := bytes.Clone(line) newLine := symbolizeLine(symbFunc, ctx.symbols, ctx.vmlinux, ctx.kernelBuildSrc, line) if prefix > len(symbolized) { prefix += len(newLine) - len(line) @@ -658,8 +657,12 @@ func (ctx *linux) decompileOpcodes(text []byte, report *Report) []byte { // Iterate over all "Code: " lines and pick the first that could be decompiled // that might be of interest to the user. var decompiled *decompiledOpcodes - var prevLine []byte - for s := bufio.NewScanner(bytes.NewReader(text)); s.Scan(); prevLine = append([]byte{}, s.Bytes()...) { + lines := lines(text) + for i, line := range lines { + var prevLine []byte + if i > 0 { + prevLine = lines[i-1] + } // We want to avoid decompiling code from user-space as it is not of big interest during // debugging kernel problems. // For now this check only works for x86/amd64, but Linux on other architectures supported @@ -667,7 +670,7 @@ func (ctx *linux) decompileOpcodes(text []byte, report *Report) []byte { if linuxUserSegmentRe.Match(prevLine) { continue } - match := linuxCodeRe.FindSubmatch(s.Bytes()) + match := linuxCodeRe.FindSubmatch(line) if match == nil { continue } @@ -731,12 +734,13 @@ func (ctx *linux) extractGuiltyFileRaw(title string, report []byte) string { } func (ctx *linux) extractGuiltyFileImpl(report []byte) string { - scanner := bufio.NewScanner(bytes.NewReader(report)) - // Extract the first possible guilty file. guilty := "" - for scanner.Scan() { - match := filenameRe.FindSubmatch(scanner.Bytes()) + var line []byte + lines := lines(report) + for len(lines) > 0 { + line, lines = lines[0], lines[1:] + match := filenameRe.FindSubmatch(line) if match == nil { continue } @@ -748,7 +752,7 @@ func (ctx *linux) extractGuiltyFileImpl(report []byte) string { guilty = string(file) } - if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(scanner.Bytes()) { + if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(line) { continue } guilty = filepath.Clean(string(file)) @@ -757,13 +761,14 @@ func (ctx *linux) extractGuiltyFileImpl(report []byte) string { // Search for deeper filepaths in the stack trace below the first possible guilty file. deepestPath := filepath.Dir(guilty) - for scanner.Scan() { - match := filenameRe.FindSubmatch(scanner.Bytes()) + for len(lines) > 0 { + line, lines = lines[0], lines[1:] + match := filenameRe.FindSubmatch(line) if match == nil { continue } file := match[1] - if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(scanner.Bytes()) { + if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(line) { continue } clean := filepath.Clean(string(file)) @@ -839,7 +844,7 @@ func (ctx *linux) isCorrupted(title string, report []byte, format oopsFormat) (b if match == nil { continue } - frames := bytes.Split(report[match[0]:], []byte{'\n'}) + frames := lines(report[match[0]:]) if len(frames) < 4 { return true, "call trace is missed" } diff --git a/pkg/report/report.go b/pkg/report/report.go index 38f2ec758..514a47734 100644 --- a/pkg/report/report.go +++ b/pkg/report/report.go @@ -6,7 +6,6 @@ package report import ( - "bufio" "bytes" "fmt" "regexp" @@ -585,9 +584,13 @@ func extractStackFrame(params *stackParams, stack *stackFmt, output []byte) ([]s return extractStackFrameImpl(params, output, skipRe, stack.parts2, extractor) } +func lines(text []byte) [][]byte { + return bytes.Split(text, []byte("\n")) +} + func extractStackFrameImpl(params *stackParams, output []byte, skipRe *regexp.Regexp, parts []*regexp.Regexp, extractor frameExtractor) ([]string, bool) { - s := bufio.NewScanner(bytes.NewReader(output)) + lines := lines(output) var frames, results []string ok := true numStackTraces := 0 @@ -607,8 +610,9 @@ nextPart: part := parts[partIdx] if part == parseStackTrace { numStackTraces++ - for s.Scan() { - ln := s.Bytes() + var ln []byte + for len(lines) > 0 { + ln, lines = lines[0], lines[1:] if matchesAny(ln, params.corruptedLines) { ok = false continue nextPart @@ -635,8 +639,9 @@ nextPart: frames = appendStackFrame(frames, match, params, skipRe) } } else { - for s.Scan() { - ln := s.Bytes() + var ln []byte + for len(lines) > 0 { + ln, lines = lines[0], lines[1:] if matchesAny(ln, params.corruptedLines) { ok = false continue nextPart |
