]> source.dussan.org Git - gitea.git/commitdiff
Prevent panic on git blame by limiting lines to 4096 bytes at most (#13492)
author6543 <6543@obermui.de>
Tue, 10 Nov 2020 07:59:38 +0000 (08:59 +0100)
committerGitHub <noreply@github.com>
Tue, 10 Nov 2020 07:59:38 +0000 (07:59 +0000)
Fix #12440
Closes #13192

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: Andrew Thornton <art27@cantab.net>
modules/git/blame.go

index 9aa77dc65b13139c9c2bfe52da162d4bccbc08d7..c2129c9e1cf1f2786a2fbd92273ffa5d038612b4 100644 (file)
@@ -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
 }
@@ -38,23 +38,30 @@ 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)}
@@ -62,12 +69,27 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 
                        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
+                       }
                }
        }
 
@@ -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