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>
bb10
Mårten Nordheim 2024-01-31 12:07:16 +01:00
parent 7ce6920aac
commit a680838be4
1 changed files with 21 additions and 12 deletions

View File

@ -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.