]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: require valid methods in NewRequest and Transport.RoundTrip
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 12 Nov 2015 15:16:06 +0000 (15:16 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 13 Nov 2015 10:13:48 +0000 (10:13 +0000)
Fixes #12078

Change-Id: If09c927fae639ec4ed3894a2b393a87c1e677803
Reviewed-on: https://go-review.googlesource.com/16829
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
src/net/http/request.go
src/net/http/request_test.go
src/net/http/transport.go
src/net/http/transport_test.go

index 8467decc182f8db5f57c3fd45cd4d68a8a699928..67976da103f359b7b86f2b356f8c7ed121057eaf 100644 (file)
@@ -547,6 +547,23 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
        return major, minor, true
 }
 
+func validMethod(method string) bool {
+       /*
+            Method         = "OPTIONS"                ; Section 9.2
+                           | "GET"                    ; Section 9.3
+                           | "HEAD"                   ; Section 9.4
+                           | "POST"                   ; Section 9.5
+                           | "PUT"                    ; Section 9.6
+                           | "DELETE"                 ; Section 9.7
+                           | "TRACE"                  ; Section 9.8
+                           | "CONNECT"                ; Section 9.9
+                           | extension-method
+          extension-method = token
+            token          = 1*<any CHAR except CTLs or separators>
+       */
+       return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
+}
+
 // NewRequest returns a new Request given a method, URL, and optional body.
 //
 // If the provided body is also an io.Closer, the returned
@@ -560,6 +577,9 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
 // type's documentation for the difference between inbound and outbound
 // request fields.
 func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
+       if !validMethod(method) {
+               return nil, fmt.Errorf("net/http: invalid method %q", method)
+       }
        u, err := url.Parse(urlStr)
        if err != nil {
                return nil, err
index 627620c0c41e5532381b65c35a7cfbba4a9b3fe8..0ed68ed66a3b8430ac44d90fb382db45140af979 100644 (file)
@@ -355,6 +355,22 @@ func TestNewRequestHost(t *testing.T) {
        }
 }
 
+func TestRequestInvalidMethod(t *testing.T) {
+       _, err := NewRequest("bad method", "http://foo.com/", nil)
+       if err == nil {
+               t.Error("expected error from NewRequest with invalid method")
+       }
+       req, err := NewRequest("GET", "http://foo.example/", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       req.Method = "bad method"
+       _, err = DefaultClient.Do(req)
+       if err == nil || !strings.Contains(err.Error(), "invalid method") {
+               t.Errorf("Transport error = %v; want invalid method", err)
+       }
+}
+
 func TestNewRequestContentLength(t *testing.T) {
        readByte := func(r io.Reader) io.Reader {
                var b [1]byte
index 17a8d7b8a7bdc8839dda070dbeb55eccf0cbc51c..96096a6bef83b52ca1c98b8a5e138badf61a96c0 100644 (file)
@@ -237,6 +237,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
                req.closeBody()
                return nil, &badStringError{"unsupported protocol scheme", s}
        }
+       if !validMethod(req.Method) {
+               return nil, fmt.Errorf("net/http: invalid method %q", req.Method)
+       }
        if req.URL.Host == "" {
                req.closeBody()
                return nil, errors.New("http: no Host in request URL")
index f721fd555810f3c357bc157c8e84f42ab2330f43..a404eeb5ccf3568fd3c2e98775d2e010f3f34c96 100644 (file)
@@ -1775,6 +1775,7 @@ func TestTransportNoHost(t *testing.T) {
        defer afterTest(t)
        tr := &Transport{}
        _, err := tr.RoundTrip(&Request{
+               Method: "GET",
                Header: make(Header),
                URL: &url.URL{
                        Scheme: "http",