diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2024-01-31 12:07:16 +0100 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2024-02-27 16:58:27 +0100 |
commit | a680838be4cf9eee44d7977722cd5acf3422f5ad (patch) | |
tree | 79a27d142e06ff6ed3a7e586c2a6d22838fe1dfd /src/network | |
parent | 7ce6920aacfcba485cd8017e01c6aeb324292e75 (diff) |
Http2: handle empty hpack block for headers
When adjusting handling for the special traling HEADERS with PRIORITY
case the actual no-headers case handling was lost.
This patch adds it back.
Now it deals with it being empty due to overflow or just empty headers.
With a real server this should never happen though, since they either
send the required headers or don't send a HEADER frame at all. So, in
theory it will not have caused a problem for users.
Pick-to: 6.7 6.6
Change-Id: Iacbb1183f26cb1f2e7e30ace6456488c4671972d
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qhttp2connection.cpp | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/src/network/access/qhttp2connection.cpp b/src/network/access/qhttp2connection.cpp index 84df04ac8b..81f7e2da61 100644 --- a/src/network/access/qhttp2connection.cpp +++ b/src/network/access/qhttp2connection.cpp @@ -1545,18 +1545,27 @@ void QHttp2Connection::handleContinuedHEADERS() HPack::BitIStream inputStream{ hpackBlock.data(), hpackBlock.data() + hpackBlock.size() }; if (!decoder.decodeHeaderFields(inputStream)) return connectionError(COMPRESSION_ERROR, "HPACK decompression failed"); - } else if (firstFrameType == FrameType::PUSH_PROMISE) { - // It could be a PRIORITY sent in HEADERS - already handled by this - // point in handleHEADERS. If it was PUSH_PROMISE (HTTP/2 8.2.1): - // "The header fields in PUSH_PROMISE and any subsequent CONTINUATION - // frames MUST be a valid and complete set of request header fields - // (Section 8.1.2.3) ... If a client receives a PUSH_PROMISE that does - // not include a complete and valid set of header fields or the :method - // pseudo-header field identifies a method that is not safe, it MUST - // respond with a stream error (Section 5.4.2) of type PROTOCOL_ERROR." - if (streamIt != m_streams.end()) - (*streamIt)->sendRST_STREAM(PROTOCOL_ERROR); - return; + } else { + if (firstFrameType == FrameType::PUSH_PROMISE) { + // It could be a PRIORITY sent in HEADERS - already handled by this + // point in handleHEADERS. If it was PUSH_PROMISE (HTTP/2 8.2.1): + // "The header fields in PUSH_PROMISE and any subsequent CONTINUATION + // frames MUST be a valid and complete set of request header fields + // (Section 8.1.2.3) ... If a client receives a PUSH_PROMISE that does + // not include a complete and valid set of header fields or the :method + // pseudo-header field identifies a method that is not safe, it MUST + // respond with a stream error (Section 5.4.2) of type PROTOCOL_ERROR." + if (streamIt != m_streams.end()) + (*streamIt)->sendRST_STREAM(PROTOCOL_ERROR); + return; + } + + // We got back an empty hpack block. Now let's figure out if there was an error. + constexpr auto hpackBlockHasContent = [](const auto &c) { return c.hpackBlockSize() > 0; }; + const bool anyHpackBlock = std::any_of(continuedFrames.cbegin(), continuedFrames.cend(), + hpackBlockHasContent); + if (anyHpackBlock) // There was hpack block data, but returned empty => it overflowed. + return connectionError(FRAME_SIZE_ERROR, "HEADERS frame too large"); } if (streamIt == m_streams.end()) // No more processing without a stream from here on. |