SP and HTAB are allowed after a = before the following CRLF.
RFC 2045 section 6.7 describes the ABNF for the quoted-printable encoding:
qp-line := *(qp-segment transport-padding CRLF)
qp-part transport-padding
qp-segment := qp-section *(SPACE / TAB) "="
transport-padding := *LWSP-char
; Composers MUST NOT generate
; non-zero length transport
; padding, but receivers MUST
; be able to handle padding
; added by message transports.
RFC 822 defines LWSP-char as:
LWSP-char = SPACE / HTAB
Dovecot's imaptest contains such a message in
src/tests/fetch-binary-mime-qp.mbox.
Fixes #70952
Change-Id: Ie05921088d7e4d6c92c4bf79b0f4a13586230753
GitHub-Last-Rev:
e6e6eee8ebc2f629644a1d99129fb57cce58058f
GitHub-Pull-Request: golang/go#70951
Reviewed-on: https://go-review.googlesource.com/c/go/+/638276
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Sean Liao <sean@liao.dev>
crlf = []byte("\r\n")
lf = []byte("\n")
softSuffix = []byte("=")
+ lwspChar = " \t"
)
// Read reads and decodes quoted-printable data from the underlying reader.
wholeLine := r.line
r.line = bytes.TrimRightFunc(wholeLine, isQPDiscardWhitespace)
if bytes.HasSuffix(r.line, softSuffix) {
- rightStripped := wholeLine[len(r.line):]
+ rightStripped := bytes.TrimLeft(wholeLine[len(r.line):], lwspChar)
r.line = r.line[:len(r.line)-1]
if !bytes.HasPrefix(rightStripped, lf) && !bytes.HasPrefix(rightStripped, crlf) &&
!(len(rightStripped) == 0 && len(r.line) > 0 && r.rerr == io.EOF) {
want: "Now's the time for all folk to come to the aid of their country."},
{in: "accept UTF-8 right quotation mark: ’",
want: "accept UTF-8 right quotation mark: ’"},
+
+ // Transport padding
+ {in: "foo= \r\nbar", want: "foobar"},
+ {in: "foo=\t \r\nbar", want: "foobar"},
}
for _, tt := range tests {
var buf strings.Builder
}
slices.Sort(outcomes)
got := strings.Join(outcomes, "\n")
- want := `OK: 28934
-invalid bytes after =: 3949
-quotedprintable: invalid hex byte 0x0d: 2048
+ want := `OK: 30638
+invalid bytes after =: 2243
+quotedprintable: invalid hex byte 0x0d: 2050
unexpected EOF: 194`
if testing.Short() {
- want = `OK: 896
-invalid bytes after =: 100
+ want = `OK: 935
+invalid bytes after =: 61
quotedprintable: invalid hex byte 0x0d: 26
unexpected EOF: 3`
}