fix fuzzing error introduced by cl/800613375 The fuzz error is triggered by gfe2_reloadable_flag_quic_fail_on_empty_ack, which itself fixes a different fuzz error due to the same behavior. The change here is an additional state check, which is low risk. I was able to repro the fuzz failure; it no longer fails. Protected by FLAGS_quic_reloadable_flag_quic_empty_ack_early_exit. PiperOrigin-RevId: 814006597
diff --git a/quiche/common/quiche_feature_flags_list.h b/quiche/common/quiche_feature_flags_list.h index bd8cf14..4792a48 100755 --- a/quiche/common/quiche_feature_flags_list.h +++ b/quiche/common/quiche_feature_flags_list.h
@@ -33,6 +33,7 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_q046, false, true, "If true, disable QUIC version Q046.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_rfcv1, false, false, "If true, disable QUIC version h3 (RFCv1).") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_discard_initial_packet_with_key_dropped, false, true, "If true, discard INITIAL packet if the key has been dropped.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disconnect_early_exit, false, false, "If true, does not update ack state if the connection has been closed.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_disable_resumption, true, true, "If true, disable resumption when receiving NRES connection option.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_mtu_discovery_at_server, false, false, "If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_server_on_wire_ping, true, true, "If true, enable server retransmittable on wire PING.")
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc index 8a2aa77..90a79e0 100644 --- a/quiche/quic/core/quic_connection.cc +++ b/quiche/quic/core/quic_connection.cc
@@ -6073,6 +6073,11 @@ } ResetAckStates(); } + if (GetQuicReloadableFlag(quic_disconnect_early_exit) && !connected_) { + // FlushAckFrame can result in a closed connection. If so, avoid updating + // ack state that could trigger QUICHE_BUGs. + return; + } const QuicTime timeout = uber_received_packet_manager_.GetEarliestAckTimeout();
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc index 2e02a64..2bc345b 100644 --- a/quiche/quic/core/quic_connection_test.cc +++ b/quiche/quic/core/quic_connection_test.cc
@@ -18195,6 +18195,43 @@ TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION); } +// Regression test for b/443473227. +TEST_P(QuicConnectionTest, DoNotUpdateAckStateAfterConnectionClose) { + if (!version().UsesTls()) { + return; + } + // Test will fail if this flag is false. + SetQuicReloadableFlag(quic_disconnect_early_exit, true); + // Path validation must occur after the handshake is confirmed. + connection_.RemoveEncrypter(ENCRYPTION_INITIAL); + connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); + // Avoid packets being held to coalesce. + EXPECT_CALL(visitor_, GetHandshakeState()) + .WillRepeatedly(Return(HANDSHAKE_CONFIRMED)); + // Silence nagging that connection_ isn't sending retransmittable frames. + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame).Times(AnyNumber()); + + // Build a big ACK frame by processing widely spaced packets. + // Must be encoded in 8 bytes when a gap. + uint64_t packet_number_increment = 0x40000002; + // Test passes if <= 134. + uint64_t max_packet_number = packet_number_increment * 135ULL; + // Make an ACK frame that is too large to fit in a single packet. + for (uint64_t packet_number = packet_number_increment; + packet_number < max_packet_number; + packet_number += packet_number_increment) { + ProcessPacket(packet_number); + } + + QuicFrames peer_frames; + peer_frames.push_back(QuicFrame(QuicPathChallengeFrame())); + writer_->SetShouldWriteFail(); + writer_->SetWriteError(-109); + EXPECT_CALL(visitor_, OnConnectionClosed); + ProcessFramesPacketAtLevel(max_packet_number, peer_frames, + ENCRYPTION_FORWARD_SECURE); +} + } // namespace } // namespace test } // namespace quic