mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Prevent panic on git blame by limiting lines to 4096 bytes at most (#13470)
Fix #12440 Closes #13192 Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
		@@ -27,7 +27,7 @@ type BlameReader struct {
 | 
				
			|||||||
	cmd     *exec.Cmd
 | 
						cmd     *exec.Cmd
 | 
				
			||||||
	pid     int64
 | 
						pid     int64
 | 
				
			||||||
	output  io.ReadCloser
 | 
						output  io.ReadCloser
 | 
				
			||||||
	scanner *bufio.Scanner
 | 
						reader  *bufio.Reader
 | 
				
			||||||
	lastSha *string
 | 
						lastSha *string
 | 
				
			||||||
	cancel  context.CancelFunc
 | 
						cancel  context.CancelFunc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -38,23 +38,30 @@ var shaLineRegex = regexp.MustCompile("^([a-z0-9]{40})")
 | 
				
			|||||||
func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
					func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
				
			||||||
	var blamePart *BlamePart
 | 
						var blamePart *BlamePart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scanner := r.scanner
 | 
						reader := r.reader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r.lastSha != nil {
 | 
						if r.lastSha != nil {
 | 
				
			||||||
		blamePart = &BlamePart{*r.lastSha, make([]string, 0)}
 | 
							blamePart = &BlamePart{*r.lastSha, make([]string, 0)}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for scanner.Scan() {
 | 
						var line []byte
 | 
				
			||||||
		line := scanner.Text()
 | 
						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 {
 | 
							if len(line) == 0 {
 | 
				
			||||||
 | 
								// isPrefix will be false
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		lines := shaLineRegex.FindStringSubmatch(line)
 | 
							lines := shaLineRegex.FindSubmatch(line)
 | 
				
			||||||
		if lines != nil {
 | 
							if lines != nil {
 | 
				
			||||||
			sha1 := lines[1]
 | 
								sha1 := string(lines[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if blamePart == nil {
 | 
								if blamePart == nil {
 | 
				
			||||||
				blamePart = &BlamePart{sha1, make([]string, 0)}
 | 
									blamePart = &BlamePart{sha1, make([]string, 0)}
 | 
				
			||||||
@@ -62,12 +69,27 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			if blamePart.Sha != sha1 {
 | 
								if blamePart.Sha != sha1 {
 | 
				
			||||||
				r.lastSha = &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
 | 
									return blamePart, nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if line[0] == '\t' {
 | 
							} else if line[0] == '\t' {
 | 
				
			||||||
			code := line[1:]
 | 
								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)
 | 
						pid := process.GetManager().Add(fmt.Sprintf("GetBlame [repo_path: %s]", dir), cancel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scanner := bufio.NewScanner(stdout)
 | 
						reader := bufio.NewReader(stdout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &BlameReader{
 | 
						return &BlameReader{
 | 
				
			||||||
		cmd,
 | 
							cmd,
 | 
				
			||||||
		pid,
 | 
							pid,
 | 
				
			||||||
		stdout,
 | 
							stdout,
 | 
				
			||||||
		scanner,
 | 
							reader,
 | 
				
			||||||
		nil,
 | 
							nil,
 | 
				
			||||||
		cancel,
 | 
							cancel,
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user