Fix coalesced packet processing
Make sure we correctly process all coalesced packets without modifying the collection while we're iterating on it.
This issue was found by clusterfuzz:
https://bugs.chromium.org/p/chromium/issues/detail?id=990001
I've confirmed that the new test fails with the old code and passes with the fix, and that the fuzzer no longer crashes.
gfe-relnote: fix coalesced packet processing, protected by disabled v99 flag
PiperOrigin-RevId: 261433275
Change-Id: Iea1edf70fc84873fc7fe2f05c749759b2c5a6c9b
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index a3ab06f..773db66 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -8562,6 +8562,53 @@
EXPECT_FALSE(ack_alarm->IsSet());
}
+// Verify that a packet containing three coalesced packets is parsed correctly.
+TEST_P(QuicConnectionTest, CoalescedPacket) {
+ if (!QuicVersionHasLongHeaderLengths(connection_.transport_version())) {
+ // Coalesced packets can only be encoded using long header lengths.
+ return;
+ }
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_TRUE(connection_.connected());
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(3);
+ } else {
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(3);
+ }
+
+ uint64_t packet_numbers[3] = {1, 2, 3};
+ EncryptionLevel encryption_levels[3] = {
+ ENCRYPTION_INITIAL, ENCRYPTION_INITIAL, ENCRYPTION_FORWARD_SECURE};
+ char buffer[kMaxOutgoingPacketSize] = {};
+ size_t total_encrypted_length = 0;
+ for (int i = 0; i < 3; i++) {
+ QuicPacketHeader header =
+ ConstructPacketHeader(packet_numbers[i], encryption_levels[i]);
+ QuicFrames frames;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frames.push_back(QuicFrame(&crypto_frame_));
+ } else {
+ frames.push_back(QuicFrame(frame1_));
+ }
+ std::unique_ptr<QuicPacket> packet = ConstructPacket(header, frames);
+ peer_creator_.set_encryption_level(encryption_levels[i]);
+ size_t encrypted_length = peer_framer_.EncryptPayload(
+ encryption_levels[i], QuicPacketNumber(packet_numbers[i]), *packet,
+ buffer + total_encrypted_length,
+ sizeof(buffer) - total_encrypted_length);
+ EXPECT_GT(encrypted_length, 0u);
+ total_encrypted_length += encrypted_length;
+ }
+ connection_.ProcessUdpPacket(
+ kSelfAddress, kPeerAddress,
+ QuicReceivedPacket(buffer, total_encrypted_length, clock_.Now(), false));
+ if (connection_.GetSendAlarm()->IsSet()) {
+ connection_.GetSendAlarm()->Fire();
+ }
+
+ EXPECT_TRUE(connection_.connected());
+}
+
} // namespace
} // namespace test
} // namespace quic