summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2024-01-31 12:07:16 +0100
committerMårten Nordheim <marten.nordheim@qt.io>2024-02-27 16:58:27 +0100
commita680838be4cf9eee44d7977722cd5acf3422f5ad (patch)
tree79a27d142e06ff6ed3a7e586c2a6d22838fe1dfd /src/network
parent7ce6920aacfcba485cd8017e01c6aeb324292e75 (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.cpp33
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.