Skip to content

Commit

Permalink
net/url: reject invalid userinfo values when parsing URLs
Browse files Browse the repository at this point in the history
Fixes #23392

Change-Id: I5822b082b14d886b9c3b5ad7beebb2c01a77851b
Reviewed-on: https://go-review.googlesource.com/87038
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
bradfitz committed Jan 10, 2018
1 parent e858a6b commit ba1018b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/net/url/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,9 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
return nil, host, nil
}
userinfo := authority[:i]
if !validUserinfo(userinfo) {
return nil, "", errors.New("net/url: invalid userinfo")
}
if !strings.Contains(userinfo, ":") {
if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
return nil, "", err
Expand Down Expand Up @@ -1069,3 +1072,33 @@ func (u *URL) UnmarshalBinary(text []byte) error {
*u = *u1
return nil
}

// validUserinfo reports whether s is a valid userinfo string per RFC 3986
// Section 3.2.1:
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
// / "*" / "+" / "," / ";" / "="
//
// It doesn't validate pct-encoded. The caller does that via func unescape.
func validUserinfo(s string) bool {
for _, r := range s {
if 'A' <= r && r <= 'Z' {
continue
}
if 'a' <= r && r <= 'z' {
continue
}
if '0' <= r && r <= '9' {
continue
}
switch r {
case '-', '.', '_', ':', '~', '!', '$', '&', '\'',
'(', ')', '*', '+', ',', ';', '=', '%', '@':
continue
default:
return false
}
}
return true
}
7 changes: 7 additions & 0 deletions src/net/url/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1735,3 +1735,10 @@ func TestNilUser(t *testing.T) {
t.Fatalf("expected empty string, got %s", v)
}
}

func TestInvalidUserPassword(t *testing.T) {
_, err := Parse("http://us\ner:pass\nword@foo.com/")
if got, wantsub := fmt.Sprint(err), "net/url: invalid userinfo"; !strings.Contains(got, wantsub) {
t.Errorf("error = %q; want substring %q", got, wantsub)
}
}

0 comments on commit ba1018b

Please sign in to comment.