Skip to content

Commit 0a72be2

Browse files
bradfitzandybons
authored andcommitted
[release-branch.go1.9] net/url: reject invalid userinfo values when parsing URLs
Fixes #23392 Change-Id: I5822b082b14d886b9c3b5ad7beebb2c01a77851b Reviewed-on: https://go-review.googlesource.com/87038 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-on: https://go-review.googlesource.com/88535 Run-TryBot: Andrew Bonventre <[email protected]>
1 parent e36f34f commit 0a72be2

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/net/url/url.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,9 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
545545
return nil, host, nil
546546
}
547547
userinfo := authority[:i]
548+
if !validUserinfo(userinfo) {
549+
return nil, "", errors.New("net/url: invalid userinfo")
550+
}
548551
if !strings.Contains(userinfo, ":") {
549552
if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
550553
return nil, "", err
@@ -1051,3 +1054,33 @@ func (u *URL) UnmarshalBinary(text []byte) error {
10511054
*u = *u1
10521055
return nil
10531056
}
1057+
1058+
// validUserinfo reports whether s is a valid userinfo string per RFC 3986
1059+
// Section 3.2.1:
1060+
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
1061+
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1062+
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1063+
// / "*" / "+" / "," / ";" / "="
1064+
//
1065+
// It doesn't validate pct-encoded. The caller does that via func unescape.
1066+
func validUserinfo(s string) bool {
1067+
for _, r := range s {
1068+
if 'A' <= r && r <= 'Z' {
1069+
continue
1070+
}
1071+
if 'a' <= r && r <= 'z' {
1072+
continue
1073+
}
1074+
if '0' <= r && r <= '9' {
1075+
continue
1076+
}
1077+
switch r {
1078+
case '-', '.', '_', ':', '~', '!', '$', '&', '\'',
1079+
'(', ')', '*', '+', ',', ';', '=', '%', '@':
1080+
continue
1081+
default:
1082+
return false
1083+
}
1084+
}
1085+
return true
1086+
}

src/net/url/url_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,3 +1683,10 @@ func TestGob(t *testing.T) {
16831683
t.Errorf("json decoded to: %s\nwant: %s\n", u1, u)
16841684
}
16851685
}
1686+
1687+
func TestInvalidUserPassword(t *testing.T) {
1688+
_, err := Parse("http://us\ner:pass\n[email protected]/")
1689+
if got, wantsub := fmt.Sprint(err), "net/url: invalid userinfo"; !strings.Contains(got, wantsub) {
1690+
t.Errorf("error = %q; want substring %q", got, wantsub)
1691+
}
1692+
}

0 commit comments

Comments
 (0)