]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: speed up cookie and method validation
authorJulien Cretel <jub0bsinthecloud@gmail.com>
Mon, 17 Feb 2025 18:39:58 +0000 (18:39 +0000)
committerGopher Robot <gobot@golang.org>
Tue, 4 Mar 2025 13:02:52 +0000 (05:02 -0800)
Fixes #67031

Change-Id: I1d764afdc7e50d61007f5f71a674eb6872ce507a
GitHub-Last-Rev: 869535e843d2133fa5279297b002dd96725384e0
GitHub-Pull-Request: golang/go#71798
Reviewed-on: https://go-review.googlesource.com/c/go/+/650195
Auto-Submit: Sean Liao <sean@liao.dev>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/net/http/cookie.go
src/net/http/http.go
src/net/http/request.go

index 3483e1638190a36203d58d817456adb590f0e317..408fe88452b37afb097bbf1fc3e9ddf5956f5b16 100644 (file)
@@ -79,7 +79,7 @@ func ParseCookie(line string) ([]*Cookie, error) {
                if !found {
                        return nil, errEqualNotFoundInCookie
                }
-               if !isCookieNameValid(name) {
+               if !isToken(name) {
                        return nil, errInvalidCookieName
                }
                value, quoted, found := parseCookieValue(value, true)
@@ -104,7 +104,7 @@ func ParseSetCookie(line string) (*Cookie, error) {
                return nil, errEqualNotFoundInCookie
        }
        name = textproto.TrimString(name)
-       if !isCookieNameValid(name) {
+       if !isToken(name) {
                return nil, errInvalidCookieName
        }
        value, quoted, ok := parseCookieValue(value, true)
@@ -225,7 +225,7 @@ func SetCookie(w ResponseWriter, cookie *Cookie) {
 // 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) {
+       if c == nil || !isToken(c.Name) {
                return ""
        }
        // extraCookieLength derived from typical length of cookie attributes
@@ -295,7 +295,7 @@ func (c *Cookie) Valid() error {
        if c == nil {
                return errors.New("http: nil Cookie")
        }
-       if !isCookieNameValid(c.Name) {
+       if !isToken(c.Name) {
                return errors.New("http: invalid Cookie.Name")
        }
        if !c.Expires.IsZero() && !validCookieExpires(c.Expires) {
@@ -349,7 +349,7 @@ func readCookies(h Header, filter string) []*Cookie {
                        }
                        name, val, _ := strings.Cut(part, "=")
                        name = textproto.TrimString(name)
-                       if !isCookieNameValid(name) {
+                       if !isToken(name) {
                                continue
                        }
                        if filter != "" && filter != name {
@@ -526,10 +526,3 @@ func parseCookieValue(raw string, allowDoubleQuote bool) (value string, quoted,
        }
        return raw, quoted, true
 }
-
-func isCookieNameValid(raw string) bool {
-       if raw == "" {
-               return false
-       }
-       return strings.IndexFunc(raw, isNotToken) < 0
-}
index e1e9eea0cefe93ef1e3d670ca7a34cfa16071775..0f9165bf037ef30d40f66b4eb2cf6ab669b2496f 100644 (file)
@@ -123,6 +123,12 @@ func isNotToken(r rune) bool {
        return !httpguts.IsTokenRune(r)
 }
 
+// isToken reports whether v is a valid token (https://www.rfc-editor.org/rfc/rfc2616#section-2.2).
+func isToken(v string) bool {
+       // For historical reasons, this function is called ValidHeaderFieldName (see issue #67031).
+       return httpguts.ValidHeaderFieldName(v)
+}
+
 // stringContainsCTLByte reports whether s contains any ASCII control character.
 func stringContainsCTLByte(s string) bool {
        for i := 0; i < len(s); i++ {
index cd254292e2a95fee998e16145d52999a216500e9..8a765c344245a6a6bb81651b5fc33aca3816c72a 100644 (file)
@@ -855,7 +855,7 @@ func validMethod(method string) bool {
           extension-method = token
             token          = 1*<any CHAR except CTLs or separators>
        */
-       return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
+       return isToken(method)
 }
 
 // NewRequest wraps [NewRequestWithContext] using [context.Background].