]> Cypherpunks repositories - gostls13.git/commitdiff
mime: don't accept single-quoted strings in media type parameter values
authorBrad Fitzpatrick <bradfitz@golang.org>
Mon, 30 Nov 2015 20:28:19 +0000 (20:28 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 1 Dec 2015 16:29:07 +0000 (16:29 +0000)
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 <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/mime/mediatype.go
src/mime/mediatype_test.go

index ad63f9bb98e9a4197070f99b82d512b9f3812eb0..00076048a1578b90bffeae6564e3f6dfdd730a86 100644 (file)
@@ -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
index 026bfa4d73468117aeca38445aedaf31122b960d..e72f95f0a0338fc2afccf9ae5a0e58b7880e6f08 100644 (file)
@@ -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) {