Skip to content

Commit a734a85

Browse files
committed
net/http: require valid methods in NewRequest and Transport.RoundTrip
Fixes #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]>
1 parent 0b314e1 commit a734a85

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

src/net/http/request.go

+20
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,23 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
547547
return major, minor, true
548548
}
549549

550+
func validMethod(method string) bool {
551+
/*
552+
Method = "OPTIONS" ; Section 9.2
553+
| "GET" ; Section 9.3
554+
| "HEAD" ; Section 9.4
555+
| "POST" ; Section 9.5
556+
| "PUT" ; Section 9.6
557+
| "DELETE" ; Section 9.7
558+
| "TRACE" ; Section 9.8
559+
| "CONNECT" ; Section 9.9
560+
| extension-method
561+
extension-method = token
562+
token = 1*<any CHAR except CTLs or separators>
563+
*/
564+
return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
565+
}
566+
550567
// NewRequest returns a new Request given a method, URL, and optional body.
551568
//
552569
// If the provided body is also an io.Closer, the returned
@@ -560,6 +577,9 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
560577
// type's documentation for the difference between inbound and outbound
561578
// request fields.
562579
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
580+
if !validMethod(method) {
581+
return nil, fmt.Errorf("net/http: invalid method %q", method)
582+
}
563583
u, err := url.Parse(urlStr)
564584
if err != nil {
565585
return nil, err

src/net/http/request_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,22 @@ func TestNewRequestHost(t *testing.T) {
355355
}
356356
}
357357

358+
func TestRequestInvalidMethod(t *testing.T) {
359+
_, err := NewRequest("bad method", "http://foo.com/", nil)
360+
if err == nil {
361+
t.Error("expected error from NewRequest with invalid method")
362+
}
363+
req, err := NewRequest("GET", "http://foo.example/", nil)
364+
if err != nil {
365+
t.Fatal(err)
366+
}
367+
req.Method = "bad method"
368+
_, err = DefaultClient.Do(req)
369+
if err == nil || !strings.Contains(err.Error(), "invalid method") {
370+
t.Errorf("Transport error = %v; want invalid method", err)
371+
}
372+
}
373+
358374
func TestNewRequestContentLength(t *testing.T) {
359375
readByte := func(r io.Reader) io.Reader {
360376
var b [1]byte

src/net/http/transport.go

+3
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
237237
req.closeBody()
238238
return nil, &badStringError{"unsupported protocol scheme", s}
239239
}
240+
if !validMethod(req.Method) {
241+
return nil, fmt.Errorf("net/http: invalid method %q", req.Method)
242+
}
240243
if req.URL.Host == "" {
241244
req.closeBody()
242245
return nil, errors.New("http: no Host in request URL")

src/net/http/transport_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,7 @@ func TestTransportNoHost(t *testing.T) {
17751775
defer afterTest(t)
17761776
tr := &Transport{}
17771777
_, err := tr.RoundTrip(&Request{
1778+
Method: "GET",
17781779
Header: make(Header),
17791780
URL: &url.URL{
17801781
Scheme: "http",

0 commit comments

Comments
 (0)