github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/email/patch.go (about)

     1  // Copyright 2017 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package email
     5  
     6  import (
     7  	"bufio"
     8  	"bytes"
     9  	"regexp"
    10  	"strings"
    11  )
    12  
    13  func ParsePatch(message []byte) (diff string) {
    14  	s := bufio.NewScanner(bytes.NewReader(message))
    15  	diffStarted := false
    16  	for s.Scan() {
    17  		ln := s.Text()
    18  		if lineMatchesDiffStart(ln) {
    19  			diffStarted = true
    20  			diff += ln + "\n"
    21  			continue
    22  		}
    23  		if diffStarted {
    24  			if ln == "" || ln == "--" || ln == "-- " || ln[0] == '>' {
    25  				diffStarted = false
    26  				continue
    27  			}
    28  			if strings.HasPrefix(ln, " ") || strings.HasPrefix(ln, "+") ||
    29  				strings.HasPrefix(ln, "-") || strings.HasPrefix(ln, "@") ||
    30  				strings.HasPrefix(ln, "================") {
    31  				diff += ln + "\n"
    32  				continue
    33  			}
    34  		}
    35  	}
    36  	err := s.Err()
    37  	if err == bufio.ErrTooLong {
    38  		// It's a problem of the incoming patch, rather than anything else.
    39  		// Anyway, if a patch contains too long lines, we're probably not
    40  		// interested in it, so let's pretent we didn't see it.
    41  		diff = ""
    42  		return
    43  	} else if err != nil {
    44  		panic("error while scanning from memory: " + err.Error())
    45  	}
    46  	return
    47  }
    48  
    49  var diffRegexps = []*regexp.Regexp{
    50  	regexp.MustCompile(`^(---|\+\+\+) [^\s]`),
    51  	regexp.MustCompile(`^diff --git`),
    52  	regexp.MustCompile(`^index [0-9a-f]+\.\.[0-9a-f]+`),
    53  	regexp.MustCompile(`^new file mode [0-9]+`),
    54  	regexp.MustCompile(`^Index: [^\s]`),
    55  }
    56  
    57  func lineMatchesDiffStart(ln string) bool {
    58  	for _, re := range diffRegexps {
    59  		if re.MatchString(ln) {
    60  			return true
    61  		}
    62  	}
    63  	return false
    64  }