Impose upper limit on the frame length of some HTTP/3 frames. This helps
prevent attacks that send malformed data.
gfe-relnote: n/a --unused code.
PiperOrigin-RevId: 242941217
Change-Id: Ic1f97f091afb57a38dc05e98ee1a5c42f1caf95a
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index 972cb37..0a2ea0d 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -26,6 +26,10 @@
// Length of the type field of HTTP/3 frames.
static const QuicByteCount kFrameTypeLength = 1;
+// Length of the weight field of a priority frame.
+static const size_t kPriorityWeightLength = 1;
+// Length of a priority frame's first byte.
+static const size_t kPriorityFirstByteLength = 1;
} // namespace
@@ -98,6 +102,12 @@
return;
}
+ if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Frame is too large");
+ visitor_->OnError(this);
+ return;
+ }
+
// Calling the following two visitor methods does not require parsing of any
// frame payload.
if (current_frame_type_ == 0x0) {
@@ -152,15 +162,10 @@
break;
}
case 0x3: { // CANCEL_PUSH
- // TODO(rch): Handle partial delivery.
BufferFramePayload(reader);
break;
}
case 0x4: { // SETTINGS
- // TODO(rch): Handle overly large SETTINGS frames. Either:
- // 1. Impose a limit on SETTINGS frame size, and close the connection if
- // exceeded
- // 2. Implement a streaming parsing mode.
BufferFramePayload(reader);
break;
}
@@ -439,4 +444,26 @@
return true;
}
+QuicByteCount HttpDecoder::MaxFrameLength(uint8_t frame_type) {
+ switch (frame_type) {
+ case 0x2: // PRIORITY
+ return kPriorityFirstByteLength + VARIABLE_LENGTH_INTEGER_LENGTH_8 * 2 +
+ kPriorityWeightLength;
+ case 0x3: // CANCEL_PUSH
+ return sizeof(PushId);
+ case 0x4: // SETTINGS
+ // This limit is arbitrary.
+ return 1024 * 1024;
+ case 0x7: // GOAWAY
+ return sizeof(QuicStreamId);
+ case 0xD: // MAX_PUSH_ID
+ return sizeof(PushId);
+ case 0xE: // DUPLICATE_PUSH
+ return sizeof(PushId);
+ default:
+ // Other frames require no data buffering, so it's safe to have no limit.
+ return std::numeric_limits<QuicByteCount>::max();
+ }
+}
+
} // namespace quic