Skip to content

Commit 72c52bf

Browse files
neildbradfitz
authored andcommitted
net/http: parse HTTP version strings according to RFC 7230
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 <[email protected]> Trust: Brad Fitzpatrick <[email protected]> Run-TryBot: Damien Neil <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent ac60900 commit 72c52bf

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-10
lines changed

src/net/http/request.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -779,11 +779,10 @@ func removeZone(host string) string {
779779
return host[:j] + host[i:]
780780
}
781781

782-
// ParseHTTPVersion parses an HTTP version string.
782+
// ParseHTTPVersion parses an HTTP version string according to RFC 7230, section 2.6.
783783
// "HTTP/1.0" returns (1, 0, true). Note that strings without
784784
// a minor version, such as "HTTP/2", are not valid.
785785
func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
786-
const Big = 1000000 // arbitrary upper bound
787786
switch vers {
788787
case "HTTP/1.1":
789788
return 1, 1, true
@@ -793,19 +792,21 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
793792
if !strings.HasPrefix(vers, "HTTP/") {
794793
return 0, 0, false
795794
}
796-
dot := strings.Index(vers, ".")
797-
if dot < 0 {
795+
if len(vers) != len("HTTP/X.Y") {
798796
return 0, 0, false
799797
}
800-
major, err := strconv.Atoi(vers[5:dot])
801-
if err != nil || major < 0 || major > Big {
798+
if vers[6] != '.' {
802799
return 0, 0, false
803800
}
804-
minor, err = strconv.Atoi(vers[dot+1:])
805-
if err != nil || minor < 0 || minor > Big {
801+
maj, err := strconv.ParseUint(vers[5:6], 10, 0)
802+
if err != nil {
803+
return 0, 0, false
804+
}
805+
min, err := strconv.ParseUint(vers[7:8], 10, 0)
806+
if err != nil {
806807
return 0, 0, false
807808
}
808-
return major, minor, true
809+
return int(maj), int(min), true
809810
}
810811

811812
func validMethod(method string) bool {

src/net/http/request_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,10 +639,10 @@ var parseHTTPVersionTests = []struct {
639639
major, minor int
640640
ok bool
641641
}{
642+
{"HTTP/0.0", 0, 0, true},
642643
{"HTTP/0.9", 0, 9, true},
643644
{"HTTP/1.0", 1, 0, true},
644645
{"HTTP/1.1", 1, 1, true},
645-
{"HTTP/3.14", 3, 14, true},
646646

647647
{"HTTP", 0, 0, false},
648648
{"HTTP/one.one", 0, 0, false},
@@ -651,6 +651,12 @@ var parseHTTPVersionTests = []struct {
651651
{"HTTP/0,-1", 0, 0, false},
652652
{"HTTP/", 0, 0, false},
653653
{"HTTP/1,1", 0, 0, false},
654+
{"HTTP/+1.1", 0, 0, false},
655+
{"HTTP/1.+1", 0, 0, false},
656+
{"HTTP/0000000001.1", 0, 0, false},
657+
{"HTTP/1.0000000001", 0, 0, false},
658+
{"HTTP/3.14", 0, 0, false},
659+
{"HTTP/12.3", 0, 0, false},
654660
}
655661

656662
func TestParseHTTPVersion(t *testing.T) {

0 commit comments

Comments
 (0)