diff options
author | ian woolf <btw515wolf2@gmail.com> | 2021-04-12 17:19:03 +0800 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2021-04-16 16:40:34 +0000 |
commit | acb189ea59d7f47e5db075e502dcce5eac6571dc (patch) | |
tree | 35feb7c9a8349b72081fe7003abb0289eea1bf23 | |
parent | 2f0e5bf907b16a8106ae68920edffe90362e16ce (diff) | |
download | go-acb189ea59d7f47e5db075e502dcce5eac6571dc.tar.gz go-acb189ea59d7f47e5db075e502dcce5eac6571dc.zip |
net/http: make ReadRequest return an error when requests have multiple Host headers
Fixes #45513
Change-Id: I59e717a4bbd3e71320deff519e4f9587ee5c8756
Reviewed-on: https://go-review.googlesource.com/c/go/+/308952
Trust: Damien Neil <dneil@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
-rw-r--r-- | src/net/http/request.go | 22 | ||||
-rw-r--r-- | src/net/http/request_test.go | 4 | ||||
-rw-r--r-- | src/net/http/server.go | 5 |
3 files changed, 16 insertions, 15 deletions
diff --git a/src/net/http/request.go b/src/net/http/request.go index ff21f19942..4a07eb1c79 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -1010,16 +1010,16 @@ func putTextprotoReader(r *textproto.Reader) { // requests and handle them via the Handler interface. ReadRequest // only supports HTTP/1.x requests. For HTTP/2, use golang.org/x/net/http2. func ReadRequest(b *bufio.Reader) (*Request, error) { - return readRequest(b, deleteHostHeader) -} + req, err := readRequest(b) + if err != nil { + return nil, err + } -// Constants for readRequest's deleteHostHeader parameter. -const ( - deleteHostHeader = true - keepHostHeader = false -) + delete(req.Header, "Host") + return req, err +} -func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err error) { +func readRequest(b *bufio.Reader) (req *Request, err error) { tp := newTextprotoReader(b) req = new(Request) @@ -1077,6 +1077,9 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro return nil, err } req.Header = Header(mimeHeader) + if len(req.Header["Host"]) > 1 { + return nil, fmt.Errorf("too many Host headers") + } // RFC 7230, section 5.3: Must treat // GET /index.html HTTP/1.1 @@ -1089,9 +1092,6 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro if req.Host == "" { req.Host = req.Header.get("Host") } - if deleteHostHeader { - delete(req.Header, "Host") - } fixPragmaCacheControl(req.Header) diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go index f09c63ed7e..07b3d6a1c7 100644 --- a/src/net/http/request_test.go +++ b/src/net/http/request_test.go @@ -469,6 +469,10 @@ var readRequestErrorTests = []struct { in: "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n", header: Header{"Content-Length": {"0"}}, }, + 11: { + in: "HEAD / HTTP/1.1\r\nHost: foo\r\nHost: bar\r\n\r\n\r\n\r\n", + err: "too many Host headers", + }, } func TestReadRequestErrors(t *testing.T) { diff --git a/src/net/http/server.go b/src/net/http/server.go index d90418b56d..e52a78e652 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -983,7 +983,7 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) { peek, _ := c.bufr.Peek(4) // ReadRequest will get err below c.bufr.Discard(numLeadingCRorLF(peek)) } - req, err := readRequest(c.bufr, keepHostHeader) + req, err := readRequest(c.bufr) if err != nil { if c.r.hitReadLimit() { return nil, errTooLarge @@ -1003,9 +1003,6 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) { if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" { return nil, badRequestError("missing required Host header") } - if len(hosts) > 1 { - return nil, badRequestError("too many Host headers") - } if len(hosts) == 1 && !httpguts.ValidHostHeader(hosts[0]) { return nil, badRequestError("malformed Host header") } |