From 7601c4bf422b92ceb77bfd99c83aa9d392906858 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 12 May 2026 14:45:56 +0000 Subject: [PATCH] net/http/internal/http2: reject STREAM_ENDED + Content-Length request We silently accepted HEADERS with END_STREAM and non-zero "content-length" header set, meaning no DATA frames will follow. The Handler saw ContentLength == 0 and EOF instead of rejecting the malformed request. Change-Id: I01e3ec3bddc4cc6c43f8bcdcfa40b0dd7d9d7f55 Reviewed-on: https://go-review.googlesource.com/c/go/+/777180 Reviewed-by: Nicholas Husin Reviewed-by: Damien Neil Auto-Submit: Damien Neil LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Reviewed-by: Nicholas Husin --- src/net/http/internal/http2/server.go | 18 +++++++++++------- src/net/http/internal/http2/server_test.go | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/net/http/internal/http2/server.go b/src/net/http/internal/http2/server.go index 1a7a09ab9e..37808dd0d2 100644 --- a/src/net/http/internal/http2/server.go +++ b/src/net/http/internal/http2/server.go @@ -2174,14 +2174,18 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res return nil, nil, err } bodyOpen := !f.StreamEnded() - if bodyOpen { - if vv, ok := rp.Header["Content-Length"]; ok { - if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil { - req.ContentLength = int64(cl) - } else { - req.ContentLength = 0 - } + if vv, ok := rp.Header["Content-Length"]; ok { + if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil { + req.ContentLength = int64(cl) } else { + req.ContentLength = 0 + } + if !bodyOpen && req.ContentLength != 0 { + return nil, nil, sc.countError("bodyless_content_length", streamError(f.StreamID, ErrCodeProtocol)) + } + } + if bodyOpen { + if _, ok := rp.Header["Content-Length"]; !ok { req.ContentLength = -1 } req.Body.(*requestBody).pipe = &pipe{ diff --git a/src/net/http/internal/http2/server_test.go b/src/net/http/internal/http2/server_test.go index f2964f4d15..6c316766a9 100644 --- a/src/net/http/internal/http2/server_test.go +++ b/src/net/http/internal/http2/server_test.go @@ -779,6 +779,20 @@ func testServer_Request_Post_Body_ContentLength_TooLarge(t testing.TB) { }) } +func TestServer_Request_Post_Body_ContentLength_EndStream(t *testing.T) { + testRejectRequest(t, func(st *serverTester) { + st.writeHeaders(HeadersFrameParam{ + StreamID: 1, // clients send odd numbers + BlockFragment: st.encodeHeader( + ":method", "POST", + "content-length", "3", + ), + EndStream: true, + EndHeaders: true, + }) + }) +} + func TestServer_Request_Post_Body_ContentLength_TooSmall(t *testing.T) { synctestTest(t, testServer_Request_Post_Body_ContentLength_TooSmall) }