aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-05-13 14:15:14 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-05-13 14:15:14 +0200
commit69423a1d41ce792ddad1c5636b61df7cb2e91440 (patch)
treecedd1e5c0d0d4c098dee2679d510509e56447176 /pkg
parent92d5fb8ed39c68c9741df483d5e50f619dacffd9 (diff)
pkg/email: allow commands in subject
Several users attempted this and there does not seem to be any reason to not allow this. So parse out command from subject as well.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/email/parser.go32
-rw-r--r--pkg/email/parser_test.go23
2 files changed, 37 insertions, 18 deletions
diff --git a/pkg/email/parser.go b/pkg/email/parser.go
index 0f4e1d40c..9c37331f7 100644
--- a/pkg/email/parser.go
+++ b/pkg/email/parser.go
@@ -4,7 +4,6 @@
package email
import (
- "bytes"
"encoding/base64"
"fmt"
"io"
@@ -104,6 +103,7 @@ func Parse(r io.Reader, ownEmails []string) (*Email, error) {
return nil, err
}
bodyStr := string(body)
+ subject := msg.Header.Get("Subject")
cmd := CmdNone
patch, cmdStr, cmdArgs := "", "", ""
if !fromMe {
@@ -116,7 +116,7 @@ func Parse(r io.Reader, ownEmails []string) (*Email, error) {
if patch == "" {
_, patch, _ = ParsePatch(bodyStr)
}
- cmd, cmdStr, cmdArgs = extractCommand(body)
+ cmd, cmdStr, cmdArgs = extractCommand(subject + "\n" + bodyStr)
}
link := ""
if match := groupsLinkRe.FindStringSubmatchIndex(bodyStr); match != nil {
@@ -126,10 +126,10 @@ func Parse(r io.Reader, ownEmails []string) (*Email, error) {
BugID: bugID,
MessageID: msg.Header.Get("Message-ID"),
Link: link,
- Subject: msg.Header.Get("Subject"),
+ Subject: subject,
From: from[0].String(),
Cc: ccList,
- Body: string(body),
+ Body: bodyStr,
Patch: patch,
Command: cmd,
CommandStr: cmdStr,
@@ -195,8 +195,8 @@ func CanonicalEmail(email string) string {
// extractCommand extracts command to syzbot from email body.
// Commands are of the following form:
// ^#syz cmd args...
-func extractCommand(body []byte) (cmd Command, str, args string) {
- cmdPos := bytes.Index(append([]byte{'\n'}, body...), []byte("\n"+commandPrefix))
+func extractCommand(body string) (cmd Command, str, args string) {
+ cmdPos := strings.Index("\n"+body, "\n"+commandPrefix)
if cmdPos == -1 {
cmd = CmdNone
return
@@ -205,17 +205,17 @@ func extractCommand(body []byte) (cmd Command, str, args string) {
for cmdPos < len(body) && body[cmdPos] == ' ' {
cmdPos++
}
- cmdEnd := bytes.IndexByte(body[cmdPos:], '\n')
+ cmdEnd := strings.IndexByte(body[cmdPos:], '\n')
if cmdEnd == -1 {
cmdEnd = len(body) - cmdPos
}
- if cmdEnd1 := bytes.IndexByte(body[cmdPos:], '\r'); cmdEnd1 != -1 && cmdEnd1 < cmdEnd {
+ if cmdEnd1 := strings.IndexByte(body[cmdPos:], '\r'); cmdEnd1 != -1 && cmdEnd1 < cmdEnd {
cmdEnd = cmdEnd1
}
- if cmdEnd1 := bytes.IndexByte(body[cmdPos:], ' '); cmdEnd1 != -1 && cmdEnd1 < cmdEnd {
+ if cmdEnd1 := strings.IndexByte(body[cmdPos:], ' '); cmdEnd1 != -1 && cmdEnd1 < cmdEnd {
cmdEnd = cmdEnd1
}
- str = string(body[cmdPos : cmdPos+cmdEnd])
+ str = body[cmdPos : cmdPos+cmdEnd]
switch str {
default:
cmd = CmdUnknown
@@ -253,14 +253,14 @@ func extractCommand(body []byte) (cmd Command, str, args string) {
return
}
-func extractArgsTokens(body []byte, num int) string {
+func extractArgsTokens(body string, num int) string {
var args []string
for pos := 0; len(args) < num && pos < len(body); {
- lineEnd := bytes.IndexByte(body[pos:], '\n')
+ lineEnd := strings.IndexByte(body[pos:], '\n')
if lineEnd == -1 {
lineEnd = len(body) - pos
}
- line := strings.TrimSpace(string(body[pos : pos+lineEnd]))
+ line := strings.TrimSpace(body[pos : pos+lineEnd])
for {
line1 := strings.Replace(line, " ", " ", -1)
if line == line1 {
@@ -276,17 +276,17 @@ func extractArgsTokens(body []byte, num int) string {
return strings.TrimSpace(strings.Join(args, " "))
}
-func extractArgsLine(body []byte) string {
+func extractArgsLine(body string) string {
pos := 0
for pos < len(body) && (body[pos] == ' ' || body[pos] == '\t' ||
body[pos] == '\n' || body[pos] == '\r') {
pos++
}
- lineEnd := bytes.IndexByte(body[pos:], '\n')
+ lineEnd := strings.IndexByte(body[pos:], '\n')
if lineEnd == -1 {
lineEnd = len(body) - pos
}
- return strings.TrimSpace(string(body[pos : pos+lineEnd]))
+ return strings.TrimSpace(body[pos : pos+lineEnd])
}
func parseBody(r io.Reader, headers mail.Header) ([]byte, [][]byte, error) {
diff --git a/pkg/email/parser_test.go b/pkg/email/parser_test.go
index 0085adeb9..ba027f8e7 100644
--- a/pkg/email/parser_test.go
+++ b/pkg/email/parser_test.go
@@ -15,13 +15,13 @@ import (
func TestExtractCommand(t *testing.T) {
for i, test := range extractCommandTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
- cmd, str, args := extractCommand([]byte(test.body))
+ cmd, str, args := extractCommand(test.body)
if cmd != test.cmd || str != test.str || !reflect.DeepEqual(args, test.args) {
t.Logf("expect: %v %q %q", test.cmd, test.str, test.args)
t.Logf("got : %v %q %q", cmd, str, args)
t.Fail()
}
- cmd, str, args = extractCommand([]byte(strings.Replace(test.body, "\n", "\r\n", -1)))
+ cmd, str, args = extractCommand(strings.Replace(test.body, "\n", "\r\n", -1))
if cmd != test.cmd || str != test.str || !reflect.DeepEqual(args, test.args) {
t.Logf("expect: %v %q %q", test.cmd, test.str, test.args)
t.Logf("got : %v %q %q", cmd, str, args)
@@ -656,4 +656,23 @@ When freeing a lockf struct that already is part of a linked list, make sure to
CommandStr: "fix:",
CommandArgs: "When freeing a lockf struct that already is part of a linked list, make sure to",
}},
+
+ {`Date: Sun, 7 May 2017 19:54:00 -0700
+Message-ID: <123>
+Subject: #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git master
+From: bob@example.com
+To: syzbot <foo+4564456@bar.com>
+
+nothing to see here`,
+ Email{
+ BugID: "4564456",
+ MessageID: "<123>",
+ Subject: "#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git master",
+ From: "<bob@example.com>",
+ Cc: []string{"bob@example.com"},
+ Body: `nothing to see here`,
+ Command: CmdTest,
+ CommandStr: "test:",
+ CommandArgs: "git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git master",
+ }},
}