net/url: disallow raw IPv6 addresses in host

RFC 3986 requires square brackets around IPv6 addresses.
Parse's acceptance of raw IPv6 addresses is non compliant,
and complicates splitting out a port.

Fixes #31024
Fixes #75223

Change-Id: I477dc420a7441cb33156627dbd5e46d88c677f1e
Reviewed-on: https://go-review.googlesource.com/c/go/+/710176
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Sean Liao 2025-10-09 01:56:09 +01:00 committed by Damien Neil
parent aced4c79a2
commit e3be2d1b2b
2 changed files with 6 additions and 21 deletions

View file

@ -698,7 +698,9 @@ func parseHost(host string) (string, error) {
return "", errors.New("invalid IP-literal")
}
return "[" + unescapedHostname + "]" + unescapedColonPort, nil
} else if i := strings.LastIndex(host, ":"); i != -1 {
} else if i := strings.Index(host, ":"); i != -1 {
// IPv4address / reg-name
// E.g. 1.2.3.4, 1.2.3.4:80, example.com, example.com:80
colonPort := host[i:]
if !validOptionalPort(colonPort) {
return "", fmt.Errorf("invalid port %q after host", colonPort)

View file

@ -506,26 +506,6 @@ var urltests = []URLTest{
},
"",
},
{
// Malformed IPv6 but still accepted.
"http://2b01:e34:ef40:7730:8e70:5aff:fefe:edac:8080/foo",
&URL{
Scheme: "http",
Host: "2b01:e34:ef40:7730:8e70:5aff:fefe:edac:8080",
Path: "/foo",
},
"",
},
{
// Malformed IPv6 but still accepted.
"http://2b01:e34:ef40:7730:8e70:5aff:fefe:edac:/foo",
&URL{
Scheme: "http",
Host: "2b01:e34:ef40:7730:8e70:5aff:fefe:edac:",
Path: "/foo",
},
"",
},
{
"http://[2b01:e34:ef40:7730:8e70:5aff:fefe:edac]:8080/foo",
&URL{
@ -735,6 +715,9 @@ var parseRequestURLTests = []struct {
{"https://[0:0::test.com]:80", false},
{"https://[2001:db8::test.com]", false},
{"https://[test.com]", false},
{"https://1:2:3:4:5:6:7:8", false},
{"https://1:2:3:4:5:6:7:8:80", false},
{"https://example.com:80:", false},
}
func TestParseRequestURI(t *testing.T) {