Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent panic on git blame by limiting lines to 4096 bytes at most (#13470) #13492

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions modules/git/blame.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type BlameReader struct {
cmd *exec.Cmd
pid int64
output io.ReadCloser
scanner *bufio.Scanner
reader *bufio.Reader
lastSha *string
cancel context.CancelFunc
}
Expand All @@ -38,36 +38,58 @@ var shaLineRegex = regexp.MustCompile("^([a-z0-9]{40})")
func (r *BlameReader) NextPart() (*BlamePart, error) {
var blamePart *BlamePart

scanner := r.scanner
reader := r.reader

if r.lastSha != nil {
blamePart = &BlamePart{*r.lastSha, make([]string, 0)}
}

for scanner.Scan() {
line := scanner.Text()
var line []byte
var isPrefix bool
var err error

for err != io.EOF {
line, isPrefix, err = reader.ReadLine()
if err != nil && err != io.EOF {
return blamePart, err
}

// Skip empty lines
if len(line) == 0 {
// isPrefix will be false
continue
}

lines := shaLineRegex.FindStringSubmatch(line)
lines := shaLineRegex.FindSubmatch(line)
if lines != nil {
sha1 := lines[1]
sha1 := string(lines[1])

if blamePart == nil {
blamePart = &BlamePart{sha1, make([]string, 0)}
}

if blamePart.Sha != sha1 {
r.lastSha = &sha1
// need to munch to end of line...
for isPrefix {
_, isPrefix, err = reader.ReadLine()
if err != nil && err != io.EOF {
return blamePart, err
}
}
return blamePart, nil
}
} else if line[0] == '\t' {
code := line[1:]

blamePart.Lines = append(blamePart.Lines, code)
blamePart.Lines = append(blamePart.Lines, string(code))
}

// need to munch to end of line...
for isPrefix {
_, isPrefix, err = reader.ReadLine()
if err != nil && err != io.EOF {
return blamePart, err
}
}
}

Expand Down Expand Up @@ -121,13 +143,13 @@ func createBlameReader(ctx context.Context, dir string, command ...string) (*Bla

pid := process.GetManager().Add(fmt.Sprintf("GetBlame [repo_path: %s]", dir), cancel)

scanner := bufio.NewScanner(stdout)
reader := bufio.NewReader(stdout)

return &BlameReader{
cmd,
pid,
stdout,
scanner,
reader,
nil,
cancel,
}, nil
Expand Down