Check that the expected and actual public header types match If a V99 server receives a packet with Google QUIC header and no version prior to version negotiation completing, it would QUIC_BUG. Now it will gracefully handle the garbage packet. gfe-relnote: Protected behind QUIC_VERSION_99 and quic_supports_tls_handshake PiperOrigin-RevId: 244398840 Change-Id: I59e58ea4254edc04087e0088c7c62fe46340421a
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index cc10cca..fcb85da 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -2465,6 +2465,10 @@ "Visitor asked to stop processing of unauthenticated header."); return false; } + if (!header->version_flag && version().KnowsWhichDecrypterToUse()) { + set_detailed_error("Invalid public header type for expected version."); + return RaiseError(QUIC_INVALID_PACKET_HEADER); + } return true; }
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index df72916..6892ea2 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -13396,6 +13396,45 @@ CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER); } +TEST_P(QuicFramerTest, ProcessPublicHeaderNoVersionInferredType) { + // The framer needs to have Perspective::IS_SERVER and configured to infer the + // packet header type from the packet (not the version). The framer's version + // needs to be one that uses the IETF packet format. + if (!framer_.version().KnowsWhichDecrypterToUse()) { + return; + } + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + + // Prepare a packet that uses the Google QUIC packet header but has no version + // field. + + // clang-format off + PacketFragments packet = { + // public flags (1-byte packet number, 8-byte connection_id, no version) + {"Unable to read public flags.", + {0x08}}, + // connection_id + {"Unable to read ConnectionId.", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"Unable to read packet number.", + {0x01}}, + // padding + {"Invalid public header type for expected version.", + {0x00}}, + }; + // clang-format on + + PacketFragments& fragments = packet; + + std::unique_ptr<QuicEncryptedPacket> encrypted( + AssemblePacketFromFragments(fragments)); + + EXPECT_FALSE(framer_.ProcessPacket(*encrypted)); + EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error()); + CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER); +} + } // namespace } // namespace test } // namespace quic