Prevent QuicStreamSequencer from taking in new data after the stream is reset. gfe-relnote: Protected by gfe2_reloadable_flag_quic_no_stream_data_after_reset. PiperOrigin-RevId: 263184076 Change-Id: I7300945bcb0bc54fc3bdd8dbafb7c8669e97afd2
diff --git a/quic/core/quic_stream_sequencer.cc b/quic/core/quic_stream_sequencer.cc index 5064bbb..fb89821 100644 --- a/quic/core/quic_stream_sequencer.cc +++ b/quic/core/quic_stream_sequencer.cc
@@ -16,6 +16,7 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_clock.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h" #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" @@ -42,10 +43,16 @@ const size_t data_len = frame.data_length; if (frame.fin) { - CloseStreamAtOffset(frame.offset + data_len); + bool should_process_data = CloseStreamAtOffset(frame.offset + data_len); if (data_len == 0) { return; } + if (GetQuicReloadableFlag(quic_no_stream_data_after_reset)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_no_stream_data_after_reset); + if (!should_process_data) { + return; + } + } } OnFrameData(byte_offset, data_len, frame.data_buffer); } @@ -109,19 +116,20 @@ } } -void QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) { +bool QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) { const QuicStreamOffset kMaxOffset = std::numeric_limits<QuicStreamOffset>::max(); // If there is a scheduled close, the new offset should match it. if (close_offset_ != kMaxOffset && offset != close_offset_) { stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS); - return; + return false; } close_offset_ = offset; MaybeCloseStream(); + return true; } void QuicStreamSequencer::MaybeCloseStream() {
diff --git a/quic/core/quic_stream_sequencer.h b/quic/core/quic_stream_sequencer.h index 1672285..e08a141 100644 --- a/quic/core/quic_stream_sequencer.h +++ b/quic/core/quic_stream_sequencer.h
@@ -167,7 +167,9 @@ void FlushBufferedFrames(); // Wait until we've seen 'offset' bytes, and then terminate the stream. - void CloseStreamAtOffset(QuicStreamOffset offset); + // Returns true if |stream_| is still available to receive data, and false if + // |stream_| is reset. + bool CloseStreamAtOffset(QuicStreamOffset offset); // If we've received a FIN and have processed all remaining data, then inform // the stream of FIN, and clear buffers.
diff --git a/quic/core/quic_stream_sequencer_test.cc b/quic/core/quic_stream_sequencer_test.cc index 60525f8..b57fa6e 100644 --- a/quic/core/quic_stream_sequencer_test.cc +++ b/quic/core/quic_stream_sequencer_test.cc
@@ -758,6 +758,17 @@ OnFinFrame(6u, "ghi"); } +// Regression test for https://crbug.com/992486. +TEST_F(QuicStreamSequencerTest, CorruptFinFrames) { + SetQuicReloadableFlag(quic_no_stream_data_after_reset, true); + EXPECT_CALL(stream_, OnDataAvailable()).Times(1); + EXPECT_CALL(stream_, Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS)); + + OnFinFrame(0u, ""); + OnFinFrame(0u, "a"); + EXPECT_FALSE(sequencer_->HasBytesToRead()); +} + } // namespace } // namespace test } // namespace quic