Commit f1d662f3 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/url, net/http: relax CTL-in-URL validation to only ASCII CTLs

CL 159157 was doing UTF-8 decoding of URLs. URLs aren't really UTF-8,
even if sometimes they are in some contexts.

Instead, only reject ASCII CTLs.

Updates #27302
Updates #22907

Change-Id: Ibd64efa5d3a93263d175aadf1c9f87deb4670c62
Reviewed-on: https://go-review.googlesource.com/c/160178
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent d34c0dbc
...@@ -59,10 +59,15 @@ func isASCII(s string) bool { ...@@ -59,10 +59,15 @@ func isASCII(s string) bool {
return true return true
} }
// isCTL reports whether r is an ASCII control character, including // stringContainsCTLByte reports whether s contains any ASCII control character.
// the Extended ASCII control characters included in Unicode. func stringContainsCTLByte(s string) bool {
func isCTL(r rune) bool { for i := 0; i < len(s); i++ {
return r < ' ' || 0x7f <= r && r <= 0x9f b := s[i]
if b < ' ' || b == 0x7f {
return true
}
}
return false
} }
func hexEscapeNonASCII(s string) string { func hexEscapeNonASCII(s string) string {
......
...@@ -550,7 +550,7 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF ...@@ -550,7 +550,7 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
ruri = r.URL.Opaque ruri = r.URL.Opaque
} }
} }
if strings.IndexFunc(ruri, isCTL) != -1 { if stringContainsCTLByte(ruri) {
return errors.New("net/http: can't write control character in Request.URL") return errors.New("net/http: can't write control character in Request.URL")
} }
// TODO: validate r.Method too? At least it's less likely to // TODO: validate r.Method too? At least it's less likely to
......
...@@ -513,7 +513,7 @@ func parse(rawurl string, viaRequest bool) (*URL, error) { ...@@ -513,7 +513,7 @@ func parse(rawurl string, viaRequest bool) (*URL, error) {
var rest string var rest string
var err error var err error
if strings.IndexFunc(rawurl, isCTL) != -1 { if stringContainsCTLByte(rawurl) {
return nil, errors.New("net/url: invalid control character in URL") return nil, errors.New("net/url: invalid control character in URL")
} }
...@@ -1139,8 +1139,13 @@ func validUserinfo(s string) bool { ...@@ -1139,8 +1139,13 @@ func validUserinfo(s string) bool {
return true return true
} }
// isCTL reports whether r is an ASCII control character, including // stringContainsCTLByte reports whether s contains any ASCII control character.
// the Extended ASCII control characters included in Unicode. func stringContainsCTLByte(s string) bool {
func isCTL(r rune) bool { for i := 0; i < len(s); i++ {
return r < ' ' || 0x7f <= r && r <= 0x9f b := s[i]
if b < ' ' || b == 0x7f {
return true
}
}
return false
} }
...@@ -1757,6 +1757,12 @@ func TestRejectControlCharacters(t *testing.T) { ...@@ -1757,6 +1757,12 @@ func TestRejectControlCharacters(t *testing.T) {
t.Errorf("Parse(%q) error = %q; want substring %q", s, got, wantSub) t.Errorf("Parse(%q) error = %q; want substring %q", s, got, wantSub)
} }
} }
// But don't reject non-ASCII CTLs, at least for now:
if _, err := Parse("http://foo.com/ctl\x80"); err != nil {
t.Errorf("error parsing URL with non-ASCII control byte: %v", err)
}
} }
var escapeBenchmarks = []struct { var escapeBenchmarks = []struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment