diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2023-04-17 12:49:12 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <wp32pw@gmail.com> | 2023-04-27 11:42:09 +0200 |
| commit | 030e10720439813a9e4a7e4586bdc2bdc781a4c9 (patch) | |
| tree | fd173364ef340c6c95b7e32f767d7f513c7cfbfd /pkg/email/parser.go | |
| parent | 3187536a2e79fb4a7c5d76ef46e69614696c3497 (diff) | |
pkg/email: support multiple commands
It's not always convenient that we can receive only one command per
email.
Update pkg/email parsing code to extract everything which there is.
Update reporting_email.go to handle multiple email commands. Set
different limits for bug email commands and bug list commands.
Diffstat (limited to 'pkg/email/parser.go')
| -rw-r--r-- | pkg/email/parser.go | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/pkg/email/parser.go b/pkg/email/parser.go index 5b472a57e..152f5e555 100644 --- a/pkg/email/parser.go +++ b/pkg/email/parser.go @@ -29,18 +29,21 @@ type Email struct { Author string OwnEmail bool Cc []string - Body string // text/plain part - Patch string // attached patch, if any - Command Command // command to bot - CommandStr string // string representation of the command - CommandArgs string // arguments for the command + Body string // text/plain part + Patch string // attached patch, if any + Commands []*SingleCommand +} + +type SingleCommand struct { + Command Command + Str string // string representation + Args string // arguments for the command } type Command int const ( CmdUnknown Command = iota - CmdNone CmdUpstream CmdFix CmdUnFix @@ -130,8 +133,8 @@ func Parse(r io.Reader, ownEmails, goodLists, domains []string) (*Email, error) } bodyStr := string(body) subject := msg.Header.Get("Subject") - cmd := CmdNone - patch, cmdStr, cmdArgs := "", "", "" + var cmds []*SingleCommand + var patch string if !fromMe { for _, a := range attachments { patch = ParsePatch(a) @@ -142,7 +145,7 @@ func Parse(r io.Reader, ownEmails, goodLists, domains []string) (*Email, error) if patch == "" { patch = ParsePatch(body) } - cmd, cmdStr, cmdArgs = extractCommand(subject + "\n" + bodyStr) + cmds = extractCommands(subject + "\n" + bodyStr) } bugIDs = append(bugIDs, extractBodyBugIDs(bodyStr, ownAddrs, domains)...) @@ -180,9 +183,7 @@ func Parse(r io.Reader, ownEmails, goodLists, domains []string) (*Email, error) Cc: ccList, Body: bodyStr, Patch: patch, - Command: cmd, - CommandStr: cmdStr, - CommandArgs: cmdArgs, + Commands: cmds, } return email, nil } @@ -241,25 +242,35 @@ func CanonicalEmail(email string) string { return strings.ToLower(addr.Address) } +func extractCommands(body string) []*SingleCommand { + var ret []*SingleCommand + for body != "" { + cmd, end := extractCommand(body) + if cmd == nil { + break + } + ret = append(ret, cmd) + body = body[end:] + } + return ret +} + const commandPrefix = "#syz" +var commandStartRe = regexp.MustCompile(`(?:^|\n)(` + regexp.QuoteMeta(commandPrefix) + `[ \t-:])`) + // extractCommand extracts command to syzbot from email body. // Commands are of the following form: // ^#syz cmd args... -func extractCommand(body string) (cmd Command, str, args string) { - nbody := "\n" + body - cmdPos := -1 - for _, delim := range []string{" ", "\t", "-", ":"} { - cmdPos = strings.Index(nbody, "\n"+commandPrefix+delim) - if cmdPos != -1 { - break - } - } - if cmdPos == -1 { - cmd = CmdNone - return +func extractCommand(body string) (*SingleCommand, int) { + var cmd Command + var str, args string + + match := commandStartRe.FindStringSubmatchIndex(body) + if match == nil { + return nil, 0 } - cmdPos += len(commandPrefix) + 1 + cmdPos := match[2] + len(commandPrefix) + 1 for cmdPos < len(body) && unicode.IsSpace(rune(body[cmdPos])) { cmdPos++ } @@ -292,15 +303,17 @@ func extractCommand(body string) (cmd Command, str, args string) { case CmdFix, CmdDup: args = extractArgsLine(body[cmdPos+cmdEnd:]) } - return + return &SingleCommand{ + Command: cmd, + Str: str, + Args: args, + }, cmdPos + cmdEnd } func strToCmd(str string) Command { switch str { default: return CmdUnknown - case "": - return CmdNone case "upstream": return CmdUpstream case "fix", "fix:": |
