Skip to content

Commit f1d662f

Browse files
committed
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent d34c0db commit f1d662f

File tree

4 files changed

+26
-10
lines changed

4 files changed

+26
-10
lines changed

src/net/http/http.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,15 @@ func isASCII(s string) bool {
5959
return true
6060
}
6161

62-
// isCTL reports whether r is an ASCII control character, including
63-
// the Extended ASCII control characters included in Unicode.
64-
func isCTL(r rune) bool {
65-
return r < ' ' || 0x7f <= r && r <= 0x9f
62+
// stringContainsCTLByte reports whether s contains any ASCII control character.
63+
func stringContainsCTLByte(s string) bool {
64+
for i := 0; i < len(s); i++ {
65+
b := s[i]
66+
if b < ' ' || b == 0x7f {
67+
return true
68+
}
69+
}
70+
return false
6671
}
6772

6873
func hexEscapeNonASCII(s string) string {

src/net/http/request.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
550550
ruri = r.URL.Opaque
551551
}
552552
}
553-
if strings.IndexFunc(ruri, isCTL) != -1 {
553+
if stringContainsCTLByte(ruri) {
554554
return errors.New("net/http: can't write control character in Request.URL")
555555
}
556556
// TODO: validate r.Method too? At least it's less likely to

src/net/url/url.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ func parse(rawurl string, viaRequest bool) (*URL, error) {
513513
var rest string
514514
var err error
515515

516-
if strings.IndexFunc(rawurl, isCTL) != -1 {
516+
if stringContainsCTLByte(rawurl) {
517517
return nil, errors.New("net/url: invalid control character in URL")
518518
}
519519

@@ -1139,8 +1139,13 @@ func validUserinfo(s string) bool {
11391139
return true
11401140
}
11411141

1142-
// isCTL reports whether r is an ASCII control character, including
1143-
// the Extended ASCII control characters included in Unicode.
1144-
func isCTL(r rune) bool {
1145-
return r < ' ' || 0x7f <= r && r <= 0x9f
1142+
// stringContainsCTLByte reports whether s contains any ASCII control character.
1143+
func stringContainsCTLByte(s string) bool {
1144+
for i := 0; i < len(s); i++ {
1145+
b := s[i]
1146+
if b < ' ' || b == 0x7f {
1147+
return true
1148+
}
1149+
}
1150+
return false
11461151
}

src/net/url/url_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,12 @@ func TestRejectControlCharacters(t *testing.T) {
17571757
t.Errorf("Parse(%q) error = %q; want substring %q", s, got, wantSub)
17581758
}
17591759
}
1760+
1761+
// But don't reject non-ASCII CTLs, at least for now:
1762+
if _, err := Parse("http://foo.com/ctl\x80"); err != nil {
1763+
t.Errorf("error parsing URL with non-ASCII control byte: %v", err)
1764+
}
1765+
17601766
}
17611767

17621768
var escapeBenchmarks = []struct {

0 commit comments

Comments
 (0)