Fix check for QuicFramer detecting old header format with new version Fixes crbug.com/958752, crbug.com/958665, crbug.com/958633 gfe-relnote: Fix bug found by fuzzer; protected by QUIC_VERSION_99 and reloadable flag quic_v44_disable_trial_decryption PiperOrigin-RevId: 246414836 Change-Id: Iac1a21476e151d382e901133a0209eadd2e17a83
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index eb1c8c0..303dca2 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -2404,7 +2404,19 @@ "Visitor asked to stop processing of unauthenticated header."); return false; } - if (!header->version_flag && version().KnowsWhichDecrypterToUse()) { + // The function we are in is called because the framer believes that it is + // processing a packet that uses the non-IETF (i.e. Google QUIC) packet header + // type. Usually, the framer makes that decision based on the framer's + // version, but when the framer is used with Perspective::IS_SERVER, then + // before version negotiation is complete (specifically, before + // InferPacketHeaderTypeFromVersion is called), this decision is made based on + // the type byte of the packet. + // + // If the framer's version KnowsWhichDecrypterToUse, then that version expects + // to use the IETF packet header type. If that's the case and we're in this + // function, then the packet received is invalid: the framer was expecting an + // IETF packet header and didn't get one. + if (version().KnowsWhichDecrypterToUse()) { set_detailed_error("Invalid public header type for expected version."); return RaiseError(QUIC_INVALID_PACKET_HEADER); }
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index 3c0b66d..aa5add5 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -13194,6 +13194,41 @@ CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER); } +TEST_P(QuicFramerTest, ProcessMismatchedHeaderVersion) { + // 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); + + // clang-format off + PacketFragments packet = { + // public flags (long header with version present) + {"Unable to read public flags.", + {0x09}}, + // connection_id + {"Unable to read ConnectionId.", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // version tag + {"Unable to read protocol version.", + {QUIC_VERSION_BYTES}}, + // packet number + {"Unable to read packet number.", + {0x01}}, + }; + // clang-format on + + std::unique_ptr<QuicEncryptedPacket> encrypted( + AssemblePacketFromFragments(packet)); + framer_.ProcessPacket(*encrypted); + + EXPECT_FALSE(framer_.ProcessPacket(*encrypted)); + EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error()); + CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER); +} + } // namespace } // namespace test } // namespace quic