aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/report
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2024-04-15 17:21:00 +0200
committerAleksandr Nogikh <nogikh@google.com>2024-04-15 15:31:30 +0000
commit68d19d39aa87674e355a2c26333a0a4d4d370018 (patch)
tree4c26e883dd7e2fc3347b0fb5baa70dd122409478 /pkg/report
parentbe2d01ee635103a77a9f68576c852f5ef3b16d0f (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.go7
-rw-r--r--pkg/report/fuchsia.go23
-rw-r--r--pkg/report/linux.go35
-rw-r--r--pkg/report/report.go17
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