mirror of
https://github.com/golang/go
synced 2024-11-23 06:40:05 -07:00
mime/multipart: fix bug when body contains prefix of the boundary
Fixes #10616 Change-Id: I4ef25eb0be6ccf474976fdb5087dd2c62c66c510 Reviewed-on: https://go-review.googlesource.com/11811 Reviewed-by: Andrew Gerrand <adg@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
1b96091a05
commit
85938714e9
@ -165,16 +165,18 @@ func (pr partReader) Read(d []byte) (n int, err error) {
|
||||
if peek == nil {
|
||||
panic("nil peek buf")
|
||||
}
|
||||
|
||||
// Search the peek buffer for "\r\n--boundary". If found,
|
||||
// consume everything up to the boundary. If not, consume only
|
||||
// as much of the peek buffer as cannot hold the boundary
|
||||
// string.
|
||||
nCopy := 0
|
||||
foundBoundary := false
|
||||
if idx := bytes.Index(peek, p.mr.nlDashBoundary); idx != -1 {
|
||||
if idx, isEnd := p.mr.peekBufferSeparatorIndex(peek); idx != -1 {
|
||||
nCopy = idx
|
||||
foundBoundary = true
|
||||
foundBoundary = isEnd
|
||||
if !isEnd && nCopy == 0 {
|
||||
nCopy = 1 // make some progress.
|
||||
}
|
||||
} else if safeCount := len(peek) - len(p.mr.nlDashBoundary); safeCount > 0 {
|
||||
nCopy = safeCount
|
||||
} else if unexpectedEOF {
|
||||
@ -338,6 +340,33 @@ func (mr *Reader) peekBufferIsEmptyPart(peek []byte) bool {
|
||||
return bytes.HasPrefix(rest, mr.nl)
|
||||
}
|
||||
|
||||
// peekBufferSeparatorIndex returns the index of mr.nlDashBoundary in
|
||||
// peek and whether it is a real boundary (and not a prefix of an
|
||||
// unrelated separator). To be the end, the peek buffer must contain a
|
||||
// newline after the boundary.
|
||||
func (mr *Reader) peekBufferSeparatorIndex(peek []byte) (idx int, isEnd bool) {
|
||||
idx = bytes.Index(peek, mr.nlDashBoundary)
|
||||
if idx == -1 {
|
||||
return
|
||||
}
|
||||
peek = peek[idx+len(mr.nlDashBoundary):]
|
||||
if len(peek) > 1 && peek[0] == '-' && peek[1] == '-' {
|
||||
return idx, true
|
||||
}
|
||||
peek = skipLWSPChar(peek)
|
||||
// Don't have a complete line after the peek.
|
||||
if bytes.IndexByte(peek, '\n') == -1 {
|
||||
return -1, false
|
||||
}
|
||||
if len(peek) > 0 && peek[0] == '\n' {
|
||||
return idx, true
|
||||
}
|
||||
if len(peek) > 1 && peek[0] == '\r' && peek[1] == '\n' {
|
||||
return idx, true
|
||||
}
|
||||
return idx, false
|
||||
}
|
||||
|
||||
// skipLWSPChar returns b with leading spaces and tabs removed.
|
||||
// RFC 822 defines:
|
||||
// LWSP-char = SPACE / HTAB
|
||||
|
@ -565,6 +565,58 @@ foo: bar
|
||||
},
|
||||
},
|
||||
|
||||
// Issue 10616; minimal
|
||||
{
|
||||
name: "issue 10616 minimal",
|
||||
sep: "sep",
|
||||
in: "--sep \r\nFoo: bar\r\n\r\n" +
|
||||
"a\r\n" +
|
||||
"--sep_alt\r\n" +
|
||||
"b\r\n" +
|
||||
"\r\n--sep--",
|
||||
want: []headerBody{
|
||||
{textproto.MIMEHeader{"Foo": {"bar"}}, "a\r\n--sep_alt\r\nb\r\n"},
|
||||
},
|
||||
},
|
||||
|
||||
// Issue 10616; full example from bug.
|
||||
{
|
||||
name: "nested separator prefix is outer separator",
|
||||
sep: "----=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9",
|
||||
in: strings.Replace(`------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9
|
||||
Content-Type: multipart/alternative; boundary="----=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt"
|
||||
|
||||
------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt
|
||||
Content-Type: text/html; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
html things
|
||||
------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt--
|
||||
------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9--`, "\n", "\r\n", -1),
|
||||
want: []headerBody{
|
||||
{textproto.MIMEHeader{"Content-Type": {`multipart/alternative; boundary="----=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt"`}},
|
||||
strings.Replace(`------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt
|
||||
Content-Type: text/html; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
html things
|
||||
------=_NextPart_4c2fbafd7ec4c8bf08034fe724b608d9_alt--`, "\n", "\r\n", -1),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
roundTripParseTest(),
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user