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