[network] Keep track of and check HTTP/2 header sizes.

This commit is contained in:
Moonchild 2024-04-17 19:10:44 +02:00 committed by roytam1
commit 1ddd3ea76b
2 changed files with 36 additions and 4 deletions

View file

@ -90,6 +90,7 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio
, mClosed(false)
, mCleanShutdown(false)
, mTLSProfileConfirmed(false)
, mAggregatedHeaderSize(0)
, mGoAwayReason(NO_HTTP_ERROR)
, mClientGoAwayReason(UNASSIGNED)
, mPeerGoAwayReason(UNASSIGNED)
@ -1262,6 +1263,13 @@ Http2Session::RecvHeaders(Http2Session *self)
RETURN_SESSION_ERROR(self, PROTOCOL_ERROR);
}
uint32_t frameSize = self->mInputFrameDataSize - paddingControlBytes -
priorityLen - paddingLength;
if (self->mAggregatedHeaderSize + frameSize >
gHttpHandler->MaxHttpResponseHeaderSize()) {
LOG(("Http2Session %p header exceeds the limit\n", self));
RETURN_SESSION_ERROR(self, PROTOCOL_ERROR);
}
if (!self->mInputFrameDataStream) {
// Cannot find stream. We can continue the session, but we need to
// uncompress the header block to maintain the correct compression context
@ -1274,7 +1282,7 @@ Http2Session::RecvHeaders(Http2Session *self)
self->GenerateRstStream(PROTOCOL_ERROR, self->mInputFrameID);
self->mDecompressBuffer.Append(&self->mInputFrameBuffer[kFrameHeaderBytes + paddingControlBytes + priorityLen],
self->mInputFrameDataSize - paddingControlBytes - priorityLen - paddingLength);
frameSize);
if (self->mInputFrameFlags & kFlag_END_HEADERS) {
rv = self->UncompressAndDiscard(false);
@ -1301,11 +1309,17 @@ Http2Session::RecvHeaders(Http2Session *self)
// queue up any compression bytes
self->mDecompressBuffer.Append(&self->mInputFrameBuffer[kFrameHeaderBytes + paddingControlBytes + priorityLen],
self->mInputFrameDataSize - paddingControlBytes - priorityLen - paddingLength);
frameSize);
self->mInputFrameDataStream->UpdateTransportReadEvents(self->mInputFrameDataSize);
self->mLastDataReadEpoch = self->mLastReadEpoch;
if (!isContinuation) {
self->mAggregatedHeaderSize = frameSize;
} else {
self->mAggregatedHeaderSize += frameSize;
}
if (!endHeadersFlag) { // more are coming - don't process yet
self->ResetDownstreamState();
return NS_OK;
@ -1613,6 +1627,15 @@ Http2Session::RecvPushPromise(Http2Session *self)
self->mInputFrameDataSize));
RETURN_SESSION_ERROR(self, PROTOCOL_ERROR);
}
uint32_t frameSize = self->mInputFrameDataSize - paddingControlBytes -
promiseLen - paddingLength;
if (self->mAggregatedHeaderSize + frameSize >
gHttpHandler->MaxHttpResponseHeaderSize()) {
LOG(("Http2Session:RecvPushPromise %p header exceeds the limit\n", self));
RETURN_SESSION_ERROR(self, PROTOCOL_ERROR);
}
LOG3(("Http2Session::RecvPushPromise %p ID 0x%X assoc ID 0x%X "
"paddingLength %d padded %d\n",
@ -1683,7 +1706,7 @@ Http2Session::RecvPushPromise(Http2Session *self)
// Need to decompress the headers even though we aren't using them yet in
// order to keep the compression context consistent for other frames
self->mDecompressBuffer.Append(&self->mInputFrameBuffer[kFrameHeaderBytes + paddingControlBytes + promiseLen],
self->mInputFrameDataSize - paddingControlBytes - promiseLen - paddingLength);
frameSize);
if (self->mInputFrameFlags & kFlag_END_PUSH_PROMISE) {
rv = self->UncompressAndDiscard(true);
if (NS_FAILED(rv)) {
@ -1697,7 +1720,13 @@ Http2Session::RecvPushPromise(Http2Session *self)
}
self->mDecompressBuffer.Append(&self->mInputFrameBuffer[kFrameHeaderBytes + paddingControlBytes + promiseLen],
self->mInputFrameDataSize - paddingControlBytes - promiseLen - paddingLength);
frameSize);
if (self->mInputFrameType != FRAME_TYPE_CONTINUATION) {
self->mAggregatedHeaderSize = frameSize;
} else {
self->mAggregatedHeaderSize += frameSize;
}
if (!(self->mInputFrameFlags & kFlag_END_PUSH_PROMISE)) {
LOG3(("Http2Session::RecvPushPromise not finishing processing for multi-frame push\n"));