github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/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 ln == "" || 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  			diffStarted = false
    35  		}
    36  	}
    37  	if diff != "" {
    38  		diff = strings.TrimRight(diff, "\n") + "\n"
    39  	}
    40  	err := s.Err()
    41  	if err == bufio.ErrTooLong {
    42  		// It's a problem of the incoming patch, rather than anything else.
    43  		// Anyway, if a patch contains too long lines, we're probably not
    44  		// interested in it, so let's pretent we didn't see it.
    45  		diff = ""
    46  		return
    47  	} else if err != nil {
    48  		panic("error while scanning from memory: " + err.Error())
    49  	}
    50  	return
    51  }
    52  
    53  var diffRegexps = []*regexp.Regexp{
    54  	regexp.MustCompile(`^(---|\+\+\+) [^\s]`),
    55  	regexp.MustCompile(`^diff --git`),
    56  	regexp.MustCompile(`^index [0-9a-f]+\.\.[0-9a-f]+`),
    57  	regexp.MustCompile(`^new file mode [0-9]+`),
    58  	regexp.MustCompile(`^Index: [^\s]`),
    59  }
    60  
    61  func lineMatchesDiffStart(ln string) bool {
    62  	for _, re := range diffRegexps {
    63  		if re.MatchString(ln) {
    64  			return true
    65  		}
    66  	}
    67  	return false
    68  }