Skip to content

Commit

Permalink
net/http: ignore Transfer-Encoding for HTTP/1.0 responses
Browse files Browse the repository at this point in the history
Fixes golang#12785

Change-Id: Iae4383889298c6a78b1ba41bd2cda70b0758fcba
Reviewed-on: https://go-review.googlesource.com/15737
Reviewed-by: Andrew Gerrand <[email protected]>
Run-TryBot: Brad Fitzpatrick <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
bradfitz committed Oct 13, 2015
1 parent 2961cab commit 2d823fd
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 11 deletions.
49 changes: 49 additions & 0 deletions src/net/http/response_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,55 @@ some body`,

"",
},

// Issue 12785: HTTP/1.0 response with bogus (to be ignored) Transfer-Encoding.
// Without a Content-Length.
{
"HTTP/1.0 200 OK\r\n" +
"Transfer-Encoding: bogus\r\n" +
"\r\n" +
"Body here\n",

Response{
Status: "200 OK",
StatusCode: 200,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Request: dummyReq("GET"),
Header: Header{},
Close: true,
ContentLength: -1,
},

"Body here\n",
},

// Issue 12785: HTTP/1.0 response with bogus (to be ignored) Transfer-Encoding.
// With a Content-Length.
{
"HTTP/1.0 200 OK\r\n" +
"Transfer-Encoding: bogus\r\n" +
"Content-Length: 10\r\n" +
"\r\n" +
"Body here\n",

Response{
Status: "200 OK",
StatusCode: 200,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Request: dummyReq("GET"),
Header: Header{
"Content-Length": {"10"},
},
Close: true,
ContentLength: 10,
},

"Body here\n",
},
}

func TestReadResponse(t *testing.T) {
Expand Down
32 changes: 21 additions & 11 deletions src/net/http/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ type transferReader struct {
Trailer Header
}

func (t *transferReader) protoAtLeast(m, n int) bool {
return t.ProtoMajor > m || (t.ProtoMajor == m && t.ProtoMinor >= n)
}

// bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC2616, section 4.4.
func bodyAllowedForStatus(status int) bool {
Expand Down Expand Up @@ -337,7 +341,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
}

// Transfer encoding, content length
t.TransferEncoding, err = fixTransferEncoding(isResponse, t.RequestMethod, t.Header)
err = t.fixTransferEncoding()
if err != nil {
return err
}
Expand Down Expand Up @@ -424,13 +428,18 @@ func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
// Checks whether the encoding is explicitly "identity".
func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }

// Sanitize transfer encoding
func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ([]string, error) {
raw, present := header["Transfer-Encoding"]
// fixTransferEncoding sanitizes t.TransferEncoding, if needed.
func (t *transferReader) fixTransferEncoding() error {
raw, present := t.Header["Transfer-Encoding"]
if !present {
return nil, nil
return nil
}
delete(t.Header, "Transfer-Encoding")

// Issue 12785; ignore Transfer-Encoding on HTTP/1.0 requests.
if !t.protoAtLeast(1, 1) {
return nil
}
delete(header, "Transfer-Encoding")

encodings := strings.Split(raw[0], ",")
te := make([]string, 0, len(encodings))
Expand All @@ -445,13 +454,13 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
break
}
if encoding != "chunked" {
return nil, &badStringError{"unsupported transfer encoding", encoding}
return &badStringError{"unsupported transfer encoding", encoding}
}
te = te[0 : len(te)+1]
te[len(te)-1] = encoding
}
if len(te) > 1 {
return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
}
if len(te) > 0 {
// RFC 7230 3.3.2 says "A sender MUST NOT send a
Expand All @@ -470,11 +479,12 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
// such a message downstream."
//
// Reportedly, these appear in the wild.
delete(header, "Content-Length")
return te, nil
delete(t.Header, "Content-Length")
t.TransferEncoding = te
return nil
}

return nil, nil
return nil
}

// Determine the expected body length, using RFC 2616 Section 4.4. This
Expand Down

0 comments on commit 2d823fd

Please sign in to comment.