From f639353330797b819f29fa2b9b4b73d09b4c7584 Mon Sep 17 00:00:00 2001 From: Hiroshi Ioka Date: Mon, 6 Mar 2017 09:59:32 +0900 Subject: [PATCH] mime: fix panic parsing 'encoded-word', be stricter Fixes #19416 Change-Id: I23c69ff637abaa202909f1cba6ed41b3cfe3d117 Reviewed-on: https://go-review.googlesource.com/37812 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/mime/encodedword.go | 17 ++++++++++++----- src/mime/encodedword_test.go | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/mime/encodedword.go b/src/mime/encodedword.go index 9de91aa3d5..dffcdef053 100644 --- a/src/mime/encodedword.go +++ b/src/mime/encodedword.go @@ -194,22 +194,29 @@ type WordDecoder struct { // Decode decodes an RFC 2047 encoded-word. func (d *WordDecoder) Decode(word string) (string, error) { - if !strings.HasPrefix(word, "=?") || !strings.HasSuffix(word, "?=") || strings.Count(word, "?") != 4 { + // See https://tools.ietf.org/html/rfc2047#section-2 + if len(word) < 9 || !strings.HasPrefix(word, "=?") || !strings.HasSuffix(word, "?=") || strings.Count(word, "?") != 4 { return "", errInvalidWord } word = word[2 : len(word)-2] // split delimits the first 2 fields split := strings.IndexByte(word, '?') + + // split word "UTF-8?q?ascii" into "UTF-8", 'q', and "ascii" + charset := word[:split] + if len(charset) == 0 { + return "", errInvalidWord + } + encoding := word[split+1] // the field after split must only be one byte if word[split+2] != '?' { return "", errInvalidWord } - - // split word "UTF-8?q?ascii" into "UTF-8", 'q', and "ascii" - charset := word[:split] - encoding := word[split+1] text := word[split+3:] + if len(text) == 0 { + return "", errInvalidWord + } content, err := decode(encoding, text) if err != nil { diff --git a/src/mime/encodedword_test.go b/src/mime/encodedword_test.go index b7ca4d05e3..ff79796042 100644 --- a/src/mime/encodedword_test.go +++ b/src/mime/encodedword_test.go @@ -88,6 +88,8 @@ func TestDecodeWord(t *testing.T) { {"=?UTF-8?Q?A=B?=", "", true}, {"=?UTF-8?Q?=A?=", "", true}, {"=?UTF-8?A?A?=", "", true}, + {"=????=", "", true}, + {"=?UTF-8?Q??=", "", true}, } for _, test := range tests {