]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: parse HTTP version strings according to RFC 7230
authorDamien Neil <dneil@google.com>
Mon, 7 Jun 2021 23:16:45 +0000 (16:16 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 6 Oct 2021 00:43:45 +0000 (00:43 +0000)
RFC 2616 permits multiple digits in the major and minor numbers of an
HTTP version:

https://datatracker.ietf.org/doc/html/rfc2616#section-3.1

RFC 7230 obsoletes 2616 and tightens the specification to permit only a
single digit in the major and minor number:

https://datatracker.ietf.org/doc/html/rfc7230#section-2.6

Use the stricter definition.

Also fix a bug which caused version numbers with a leading "+" to
be accepted (e.g., "HTTP/1.+1".)

Fixes #46587.

Change-Id: Ic5923bb858e5ac402cfde486fba2c075e221553d
Reviewed-on: https://go-review.googlesource.com/c/go/+/325874
Trust: Damien Neil <dneil@google.com>
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/http/request.go
src/net/http/request_test.go

index 09cb0c7f564f745f1b50c9f861f441603055e764..0eb7042d7b6b510f6fc092d2a88ebb3da17bad46 100644 (file)
@@ -779,11 +779,10 @@ func removeZone(host string) string {
        return host[:j] + host[i:]
 }
 
-// ParseHTTPVersion parses an HTTP version string.
+// ParseHTTPVersion parses an HTTP version string according to RFC 7230, section 2.6.
 // "HTTP/1.0" returns (1, 0, true). Note that strings without
 // a minor version, such as "HTTP/2", are not valid.
 func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
-       const Big = 1000000 // arbitrary upper bound
        switch vers {
        case "HTTP/1.1":
                return 1, 1, true
@@ -793,19 +792,21 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
        if !strings.HasPrefix(vers, "HTTP/") {
                return 0, 0, false
        }
-       dot := strings.Index(vers, ".")
-       if dot < 0 {
+       if len(vers) != len("HTTP/X.Y") {
                return 0, 0, false
        }
-       major, err := strconv.Atoi(vers[5:dot])
-       if err != nil || major < 0 || major > Big {
+       if vers[6] != '.' {
                return 0, 0, false
        }
-       minor, err = strconv.Atoi(vers[dot+1:])
-       if err != nil || minor < 0 || minor > Big {
+       maj, err := strconv.ParseUint(vers[5:6], 10, 0)
+       if err != nil {
+               return 0, 0, false
+       }
+       min, err := strconv.ParseUint(vers[7:8], 10, 0)
+       if err != nil {
                return 0, 0, false
        }
-       return major, minor, true
+       return int(maj), int(min), true
 }
 
 func validMethod(method string) bool {
index 4e0c4ba207f8be66a7f529de7aa7ac7fb052021a..4363e1103332567d28e7d0a4103945241cda87a1 100644 (file)
@@ -639,10 +639,10 @@ var parseHTTPVersionTests = []struct {
        major, minor int
        ok           bool
 }{
+       {"HTTP/0.0", 0, 0, true},
        {"HTTP/0.9", 0, 9, true},
        {"HTTP/1.0", 1, 0, true},
        {"HTTP/1.1", 1, 1, true},
-       {"HTTP/3.14", 3, 14, true},
 
        {"HTTP", 0, 0, false},
        {"HTTP/one.one", 0, 0, false},
@@ -651,6 +651,12 @@ var parseHTTPVersionTests = []struct {
        {"HTTP/0,-1", 0, 0, false},
        {"HTTP/", 0, 0, false},
        {"HTTP/1,1", 0, 0, false},
+       {"HTTP/+1.1", 0, 0, false},
+       {"HTTP/1.+1", 0, 0, false},
+       {"HTTP/0000000001.1", 0, 0, false},
+       {"HTTP/1.0000000001", 0, 0, false},
+       {"HTTP/3.14", 0, 0, false},
+       {"HTTP/12.3", 0, 0, false},
 }
 
 func TestParseHTTPVersion(t *testing.T) {