]> Cypherpunks repositories - gostls13.git/commitdiff
net/url: reject colon in first segment of relative path in Parse
authorRuss Cox <rsc@golang.org>
Thu, 20 Oct 2016 20:53:49 +0000 (16:53 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 24 Oct 2016 16:04:47 +0000 (16:04 +0000)
RFC 3986 §3.3 disallows relative URL paths in which the first segment
contains a colon, presumably to avoid confusion with scheme:foo syntax,
which is exactly what happened in #16822.

Fixes #16822.

Change-Id: Ie4449e1dd21c5e56e3b126e086c3a0b05da7ff24
Reviewed-on: https://go-review.googlesource.com/31582
Reviewed-by: Quentin Smith <quentin@golang.org>
src/net/url/url.go
src/net/url/url_test.go

index 0931296468239a5c796bf69f7bf84b6c11e8ff7c..42a514bbc129ef2248acc03a466bea58e7680583 100644 (file)
@@ -503,6 +503,19 @@ func parse(rawurl string, viaRequest bool) (*URL, error) {
                if viaRequest {
                        return nil, errors.New("invalid URI for request")
                }
+
+               // Avoid confusion with malformed schemes, like cache_object:foo/bar.
+               // See golang.org/issue/16822.
+               //
+               // RFC 3986, §3.3:
+               // In addition, a URI reference (Section 4.1) may be a relative-path reference,
+               // in which case the first path segment cannot contain a colon (":") character.
+               colon := strings.Index(rest, ":")
+               slash := strings.Index(rest, "/")
+               if colon >= 0 && (slash < 0 || colon < slash) {
+                       // First path segment has colon. Not allowed in relative URL.
+                       return nil, errors.New("first path segment in URL cannot contain colon")
+               }
        }
 
        if (url.Scheme != "" || !viaRequest && !strings.HasPrefix(rest, "///")) && strings.HasPrefix(rest, "//") {
index eebc1112c1552da10de1b7fc898175392133a3a7..6c3bb21d20cb367d8823b364e91ed8f69c349af3 100644 (file)
@@ -1385,7 +1385,7 @@ func TestParseFailure(t *testing.T) {
        }
 }
 
-func TestParseAuthority(t *testing.T) {
+func TestParseErrors(t *testing.T) {
        tests := []struct {
                in      string
                wantErr bool
@@ -1405,9 +1405,13 @@ func TestParseAuthority(t *testing.T) {
                {"http://%41:8080/", true},        // not allowed: % encoding only for non-ASCII
                {"mysql://x@y(z:123)/foo", false}, // golang.org/issue/12023
                {"mysql://x@y(1.2.3.4:123)/foo", false},
-               {"mysql://x@y([2001:db8::1]:123)/foo", false},
+
                {"http://[]%20%48%54%54%50%2f%31%2e%31%0a%4d%79%48%65%61%64%65%72%3a%20%31%32%33%0a%0a/", true}, // golang.org/issue/11208
                {"http://a b.com/", true},                                                                       // no space in host name please
+               {"cache_object://foo", true},                                                                    // scheme cannot have _, relative path cannot have : in first segment
+               {"cache_object:foo", true},
+               {"cache_object:foo/bar", true},
+               {"cache_object/:foo/bar", false},
        }
        for _, tt := range tests {
                u, err := Parse(tt.in)