]> Cypherpunks repositories - gostls13.git/commitdiff
net/mail: improve detection of charset errors
authorRuss Cox <rsc@golang.org>
Wed, 13 Jan 2021 15:53:48 +0000 (10:53 -0500)
committerGopher Robot <gobot@golang.org>
Fri, 25 Mar 2022 19:04:59 +0000 (19:04 +0000)
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 <iant@golang.org>
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/net/mail/message.go
src/net/mail/message_test.go

index 985b6fcae271bc9eba8993e87b290f2723007422..5770e3d8dc6db52ccc701a2724ed977d03bb22ae 100644 (file)
@@ -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
        }
 
index 80a17b2853ae45bbec72c2944e10f95ba05e47b6..41c54b868777049d539575ca4860063360277b92 100644 (file)
@@ -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) {