Skip to content

Commit 98a934c

Browse files
fstachurarjarry
authored andcommitted
mail: handle multipart without closing boundary
Emails with multipart that was not properly closed may cause the parser to go into an infinite loop. In that case, io.Copy in findTextParts may return a de-facto EOF that is not *the* io.EOF. (Same with NextPart, this is not handled in this commit as I don't have a test case). Introduce an arbitrary limit of parts to prevent this from happening in the future. Also, add another error handler for this special unexpected EOF. Signed-off-by: Franciszek Stachura <fbstachura@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
1 parent 1c8949a commit 98a934c

3 files changed

Lines changed: 37 additions & 1 deletion

File tree

‎pkg/mail/content.go‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ func findTextParts(m *mail.Reader) []textPart {
2626
var results []textPart
2727
var buf strings.Builder
2828

29-
for {
29+
// Arbitrary limit of parts to prevent an infinite loop
30+
for range 1024 {
3031
part, err := m.NextPart()
3132
if errors.Is(err, io.EOF) {
3233
break
@@ -57,6 +58,10 @@ func findTextParts(m *mail.Reader) []textPart {
5758

5859
buf.Reset()
5960
if n, err := io.Copy(&buf, part.Body); err != nil {
61+
if strings.Contains(err.Error(), "EOF") {
62+
break
63+
}
64+
6065
log.Warnf("failed to read part body: %s", err)
6166
continue
6267
} else if n == 0 {

‎pkg/mail/content_test.go‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,10 @@ func TestInvalidCharset(t *testing.T) {
149149
assert.NotEmpty(t, diff, "expected diff despite invalid charset")
150150
assert.NotEmpty(t, comment, "expected comment despite invalid charset")
151151
}
152+
153+
func TestMultipartWithoutClosingBoundary(t *testing.T) {
154+
m := openTestMail(t, "mail/0028-multipart-without-closing-boundary.mbox")
155+
diff, comment := FindPatchContent(m)
156+
assert.Empty(t, diff, "expected no diff")
157+
assert.NotEmpty(t, comment, "expected a comment despite multipart without closing boundary")
158+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
From stephenfinucane@hotmail.com Wed Jun 20 13:35:48 2018
2+
From: Stephen Finucane <stephenfinucane@hotmail.com>
3+
To: "stephen@that.guru" <stephen@that.guru>
4+
Subject: Re: [PATCH] parsemail: ignore html part of multi-part comments
5+
Date: Wed, 20 Jun 2018 13:35:37 +0000
6+
Message-ID: <DB5PR03MB18774049A0E62D211988EC8CA3770@DB5PR03MB1877.eurprd03.prod.outlook.com>
7+
References: <20180620122142.9917-1-yuri.volchkov@gmail.com>
8+
In-Reply-To: <20180620122142.9917-1-yuri.volchkov@gmail.com>
9+
Content-Type: multipart/alternative;
10+
boundary="_000_DB5PR03MB18774049A0E62D211988EC8CA3770DB5PR03MB1877eurp_"
11+
MIME-Version: 1.0
12+
13+
14+
--_000_DB5PR03MB18774049A0E62D211988EC8CA3770DB5PR03MB1877eurp_
15+
Content-Type: text/plain; charset="iso-8859-1"
16+
Content-Transfer-Encoding: 8bit
17+
18+
Yup, this looks sensible to me. Replying from Outlook's awful HTML editor to get
19+
a sample comment to test with.
20+
21+
Stephen
22+
23+
24+
--_000_DB5PR03MB18774049A0E62D211988EC8CA3770DB5PR03MB1877eurp_

0 commit comments

Comments
 (0)