]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: harden, document func SetCookie and type Cookie
authorBrad Fitzpatrick <bradfitz@golang.org>
Tue, 30 Jun 2015 01:10:43 +0000 (18:10 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 30 Jun 2015 16:19:02 +0000 (16:19 +0000)
Fixes #9758

Change-Id: I3089ec06cddd74b547d8b10834d7478a04b02069
Reviewed-on: https://go-review.googlesource.com/11701
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/net/http/cookie.go
src/net/http/cookie_test.go

index 635a265706a9812be1e65a547498f60dc8824f97..cf7a3dbe5b3c257abb3cc1a7d54a82fc0e0e13a1 100644 (file)
@@ -14,19 +14,18 @@ import (
        "time"
 )
 
-// This implementation is done according to RFC 6265:
-//
-//    http://tools.ietf.org/html/rfc6265
-
 // A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
 // HTTP response or the Cookie header of an HTTP request.
+//
+// See http://tools.ietf.org/html/rfc6265 for details.
 type Cookie struct {
-       Name       string
-       Value      string
-       Path       string
-       Domain     string
-       Expires    time.Time
-       RawExpires string
+       Name  string
+       Value string
+
+       Path       string    // optional
+       Domain     string    // optional
+       Expires    time.Time // optional
+       RawExpires string    // for reading cookies only
 
        // MaxAge=0 means no 'Max-Age' attribute specified.
        // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
@@ -126,14 +125,22 @@ func readSetCookies(h Header) []*Cookie {
 }
 
 // SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
+// The provided cookie must have a valid Name. Invalid cookies may be
+// silently dropped.
 func SetCookie(w ResponseWriter, cookie *Cookie) {
-       w.Header().Add("Set-Cookie", cookie.String())
+       if v := cookie.String(); v != "" {
+               w.Header().Add("Set-Cookie", v)
+       }
 }
 
 // String returns the serialization of the cookie for use in a Cookie
 // header (if only Name and Value are set) or a Set-Cookie response
 // header (if other fields are set).
+// If c is nil or c.Name is invalid, the empty string is returned.
 func (c *Cookie) String() string {
+       if c == nil || !isCookieNameValid(c.Name) {
+               return ""
+       }
        var b bytes.Buffer
        fmt.Fprintf(&b, "%s=%s", sanitizeCookieName(c.Name), sanitizeCookieValue(c.Value))
        if len(c.Path) > 0 {
@@ -359,5 +366,8 @@ func parseCookieValue(raw string, allowDoubleQuote bool) (string, bool) {
 }
 
 func isCookieNameValid(raw string) bool {
+       if raw == "" {
+               return false
+       }
        return strings.IndexFunc(raw, isNotToken) < 0
 }
index bcad88c012120995bf9c396bc53a9617de86b1a6..d474f313476dca72f0a3717413b9dab9555d8f56 100644 (file)
@@ -94,6 +94,18 @@ var writeSetCookiesTests = []struct {
                &Cookie{Name: "empty-value", Value: ""},
                `empty-value=`,
        },
+       {
+               nil,
+               ``,
+       },
+       {
+               &Cookie{Name: ""},
+               ``,
+       },
+       {
+               &Cookie{Name: "\t"},
+               ``,
+       },
 }
 
 func TestWriteSetCookies(t *testing.T) {