From cdce82485047bd0f7f5dc31d27326bb4ca869e53 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 29 Jun 2018 19:23:35 +0000 Subject: [PATCH] net/http: update bundled http2 Updates http2 to x/net/http2 git rev 97aa3a539 for: http2: dynamic table updates must occur first https://golang.org/cl/111681 http2: receiving too much data is a protocol error https://golang.org/cl/111679 http2: correct overflow protection https://golang.org/cl/111675 http2: make Server send GOAWAY if Handler sets "Connection: close" header https://golang.org/cl/121415 Fixes #20977 Change-Id: I9b8659b5191409ed007e2d911913763bcbabb7cc Reviewed-on: https://go-review.googlesource.com/121695 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/net/http/clientserver_test.go | 1 - src/net/http/h2_bundle.go | 32 ++++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go index b894be0813..c2a2548df1 100644 --- a/src/net/http/clientserver_test.go +++ b/src/net/http/clientserver_test.go @@ -1232,7 +1232,6 @@ func TestH12_AutoGzipWithDumpResponse(t *testing.T) { h := w.Header() h.Set("Content-Encoding", "gzip") h.Set("Content-Length", "23") - h.Set("Connection", "keep-alive") io.WriteString(w, "\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00") }, EarlyCheckResponse: func(proto string, res *Response) { diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index f0dd8e6c76..053f81e257 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1290,12 +1290,12 @@ func (f *http2flow) take(n int32) { // add adds n bytes (positive or negative) to the flow control window. // It returns false if the sum would exceed 2^31-1. func (f *http2flow) add(n int32) bool { - remain := (1<<31 - 1) - f.n - if n > remain { - return false + sum := f.n + n + if (sum > n) == (f.n > 0) { + f.n = sum + return true } - f.n += n - return true + return false } const http2frameHeaderLen = 9 @@ -5302,7 +5302,10 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { // Sender sending more than they'd declared? if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes { st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes)) - return http2streamError(id, http2ErrCodeStreamClosed) + // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the + // value of a content-length header field does not equal the sum of the + // DATA frame payload lengths that form the body. + return http2streamError(id, http2ErrCodeProtocol) } if f.Length > 0 { // Check whether the client has flow control quota. @@ -6038,6 +6041,19 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) { http2foreachHeaderElement(v, rws.declareTrailer) } + // "Connection" headers aren't allowed in HTTP/2 (RFC 7540, 8.1.2.2), + // but respect "Connection" == "close" to mean sending a GOAWAY and tearing + // down the TCP connection when idle, like we do for HTTP/1. + // TODO: remove more Connection-specific header fields here, in addition + // to "Connection". + if _, ok := rws.snapHeader["Connection"]; ok { + v := rws.snapHeader.Get("Connection") + delete(rws.snapHeader, "Connection") + if v == "close" { + rws.conn.startGracefulShutdown() + } + } + endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp err = rws.conn.writeHeaders(rws.stream, &http2writeResHeaders{ streamID: rws.stream.id, @@ -6845,9 +6861,7 @@ func (http2noCachedConnError) Error() string { return "http2: no cached connecti // or its equivalent renamed type in net/http2's h2_bundle.go. Both types // may coexist in the same running program. func http2isNoCachedConnError(err error) bool { - _, ok := err.(interface { - IsHTTP2NoCachedConnError() - }) + _, ok := err.(interface{ IsHTTP2NoCachedConnError() }) return ok } -- 2.50.0