Skip to content

Commit

Permalink
net/http: require valid methods in NewRequest and Transport.RoundTrip
Browse files Browse the repository at this point in the history
Fixes golang#12078

Change-Id: If09c927fae639ec4ed3894a2b393a87c1e677803
Reviewed-on: https://go-review.googlesource.com/16829
Run-TryBot: Brad Fitzpatrick <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Andrew Gerrand <[email protected]>
  • Loading branch information
bradfitz committed Nov 13, 2015
1 parent 0b314e1 commit a734a85
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/net/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions src/net/http/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/net/http/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
1 change: 1 addition & 0 deletions src/net/http/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit a734a85

Please sign in to comment.