Replace a DCHECK with a parse failure in connection ID parsing
This issue was found by ClusterFuzz:
https://bugs.chromium.org/p/chromium/issues/detail?id=962900
On the client, when parsing an IETF long header, we do not expect there to be a destination connection ID as we do not support client connection IDs yet. Instead of having a DCHECK to verify that, we should fail parsing with QUIC_INVALID_PACKET_HEADER.
gfe-relnote: change how client reacts to a type of invalid packet, client-only.
PiperOrigin-RevId: 248442467
Change-Id: Ie13868e5c45c0868c0f0d8655546ea927d705753
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index f0954d1..b686068 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -2699,8 +2699,13 @@
if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
if (header->source_connection_id_included == CONNECTION_ID_PRESENT) {
+ DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
+ DCHECK_EQ(IETF_QUIC_LONG_HEADER_PACKET, header->form);
+ if (!header->destination_connection_id.IsEmpty()) {
+ set_detailed_error("Client connection ID not supported yet.");
+ return false;
+ }
// Set destination connection ID to source connection ID.
- DCHECK_EQ(EmptyQuicConnectionId(), header->destination_connection_id);
header->destination_connection_id = header->source_connection_id;
} else if (header->destination_connection_id_included ==
CONNECTION_ID_ABSENT) {
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index f196e5d..347df84 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -13701,6 +13701,49 @@
parsed_probe_payload_bytes, parsed_probe_payload_length);
}
+TEST_P(QuicFramerTest, ClientConnectionIdNotSupportedYet) {
+ if (GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ // This check is currently only performed when this flag is disabled.
+ return;
+ }
+ if (framer_.transport_version() <= QUIC_VERSION_43) {
+ // This test requires an IETF long header.
+ return;
+ }
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+ const unsigned char type_byte =
+ framer_.transport_version() == QUIC_VERSION_44 ? 0xFC : 0xD3;
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ type_byte,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x50,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // long header packet length
+ 0x05,
+ // packet number
+ 0x12, 0x34, 0x56, 0x00,
+ // padding frame
+ 0x00,
+ };
+ // clang-format on
+ EXPECT_FALSE(framer_.ProcessPacket(
+ QuicEncryptedPacket(AsChars(packet), QUIC_ARRAYSIZE(packet), false)));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ framer_.transport_version())) {
+ EXPECT_EQ("Invalid ConnectionId length.", framer_.detailed_error());
+ } else {
+ EXPECT_EQ("Client connection ID not supported yet.",
+ framer_.detailed_error());
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic