From 2bbf383774952c8ddc309a45c024af76b47ea1fe Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Jan 2021 10:53:48 -0500 Subject: [PATCH] net/mail: improve detection of charset errors The detection of the "unknown charset" case was too tailored to one specific address parser. Make it generalize, so that custom address parsers behave the same way as the default one for character sets they do not handle. Fixes #41625. Change-Id: I347d4bb6844d0a1f23e908b776d21e8be5af3874 Reviewed-on: https://go-review.googlesource.com/c/go/+/283632 Reviewed-by: Ian Lance Taylor Trust: Russ Cox Run-TryBot: Russ Cox Auto-Submit: Russ Cox TryBot-Result: Gopher Robot --- src/net/mail/message.go | 36 ++++++++++++++++++++++++++++++------ src/net/mail/message_test.go | 11 +++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/net/mail/message.go b/src/net/mail/message.go index 985b6fcae2..5770e3d8dc 100644 --- a/src/net/mail/message.go +++ b/src/net/mail/message.go @@ -745,17 +745,41 @@ func (p *addrParser) consumeComment() (string, bool) { } func (p *addrParser) decodeRFC2047Word(s string) (word string, isEncoded bool, err error) { - if p.dec != nil { - word, err = p.dec.Decode(s) - } else { - word, err = rfc2047Decoder.Decode(s) + dec := p.dec + if dec == nil { + dec = &rfc2047Decoder + } + + // Substitute our own CharsetReader function so that we can tell + // whether an error from the Decode method was due to the + // CharsetReader (meaning the charset is invalid). + // We used to look for the charsetError type in the error result, + // but that behaves badly with CharsetReaders other than the + // one in rfc2047Decoder. + adec := *dec + charsetReaderError := false + adec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) { + if dec.CharsetReader == nil { + charsetReaderError = true + return nil, charsetError(charset) + } + r, err := dec.CharsetReader(charset, input) + if err != nil { + charsetReaderError = true + } + return r, err } - + word, err = adec.Decode(s) if err == nil { return word, true, nil } - if _, ok := err.(charsetError); ok { + // If the error came from the character set reader + // (meaning the character set itself is invalid + // but the decoding worked fine until then), + // return the original text and the error, + // with isEncoded=true. + if charsetReaderError { return s, true, err } diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go index 80a17b2853..41c54b8687 100644 --- a/src/net/mail/message_test.go +++ b/src/net/mail/message_test.go @@ -344,6 +344,17 @@ func TestAddressParsingError(t *testing.T) { t.Errorf(`mail.ParseAddress(%q) #%d want %q, got %v`, tc.text, i, tc.wantErrText, err) } } + + t.Run("CustomWordDecoder", func(t *testing.T) { + p := &AddressParser{WordDecoder: &mime.WordDecoder{}} + for i, tc := range mustErrTestCases { + _, err := p.Parse(tc.text) + if err == nil || !strings.Contains(err.Error(), tc.wantErrText) { + t.Errorf(`p.Parse(%q) #%d want %q, got %v`, tc.text, i, tc.wantErrText, err) + } + } + }) + } func TestAddressParsing(t *testing.T) { -- 2.48.1