From a3f99dc4e9499c88a784e94ada3c2bd419438c51 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 30 Nov 2015 20:28:19 +0000 Subject: [PATCH] mime: don't accept single-quoted strings in media type parameter values Fix an old bug where media type parameter values could be escaped by either double quotes (per the spec) or single quotes (due to my bug). The original bug was introduced by me in git rev 90e4ece3 (https://golang.org/cl/4430049) in April 2011 when adding more tests from http://greenbytes.de/tech/tc2231/ and misinterpreting the expected value of test "attwithfntokensq" and not apparently thinking about it enough. No known spec or existing software produces or expects single quotes around values. In fact, it would have be a parsing ambiguity if it were allowed: the string `a=', b='` could parse as two keys "a" and "b" both with value "'", or it could be parse as a single key "a" with value "', b=". Fixes #11291 Change-Id: I6de58009dd47dcabb120b017245d237cb7b1e89a Reviewed-on: https://go-review.googlesource.com/17136 Reviewed-by: Russ Cox Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/mime/mediatype.go | 13 ++++++------- src/mime/mediatype_test.go | 3 ++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mime/mediatype.go b/src/mime/mediatype.go index ad63f9bb98e..00076048a15 100644 --- a/src/mime/mediatype.go +++ b/src/mime/mediatype.go @@ -237,24 +237,23 @@ func consumeToken(v string) (token, rest string) { // quoted-string) and the rest of the string. On failure, returns // ("", v). func consumeValue(v string) (value, rest string) { - if !strings.HasPrefix(v, `"`) && !strings.HasPrefix(v, `'`) { + if v == "" { + return + } + if v[0] != '"' { return consumeToken(v) } - leadQuote := rune(v[0]) - // parse a quoted-string rest = v[1:] // consume the leading quote buffer := new(bytes.Buffer) - var idx int - var r rune var nextIsLiteral bool - for idx, r = range rest { + for idx, r := range rest { switch { case nextIsLiteral: buffer.WriteRune(r) nextIsLiteral = false - case r == leadQuote: + case r == '"': return buffer.String(), rest[idx+1:] case r == '\\': nextIsLiteral = true diff --git a/src/mime/mediatype_test.go b/src/mime/mediatype_test.go index 026bfa4d734..e72f95f0a03 100644 --- a/src/mime/mediatype_test.go +++ b/src/mime/mediatype_test.go @@ -159,7 +159,7 @@ func TestParseMediaType(t *testing.T) { m("filename", "foo.html")}, {`attachment; filename='foo.html'`, "attachment", - m("filename", "foo.html")}, + m("filename", "'foo.html'")}, {`attachment; filename="foo-%41.html"`, "attachment", m("filename", "foo-%41.html")}, @@ -294,6 +294,7 @@ var formatTests = []formatTest{ {"foo/BAR", map[string]string{"bad attribute": "baz"}, ""}, {"foo/BAR", map[string]string{"nonascii": "not an ascii character: รค"}, ""}, {"foo/bar", map[string]string{"a": "av", "b": "bv", "c": "cv"}, "foo/bar; a=av; b=bv; c=cv"}, + {"foo/bar", map[string]string{"0": "'", "9": "'"}, "foo/bar; 0='; 9='"}, } func TestFormatMediaType(t *testing.T) {