Index: net/quic/quic_session_test.cc |
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc |
index a81d1f5bb116025fe696c70a76a56141f4f41a04..b604a7ffee1f19c3b0793913313cbc4f6d123974 100644 |
--- a/net/quic/quic_session_test.cc |
+++ b/net/quic/quic_session_test.cc |
@@ -11,6 +11,7 @@ |
#include "base/containers/hash_tables.h" |
#include "net/quic/crypto/crypto_protocol.h" |
#include "net/quic/quic_crypto_stream.h" |
+#include "net/quic/quic_flags.h" |
#include "net/quic/quic_protocol.h" |
#include "net/quic/quic_utils.h" |
#include "net/quic/reliable_quic_stream.h" |
@@ -903,6 +904,35 @@ TEST_P(QuicSessionTest, VersionNegotiationDisablesFlowControl) { |
EXPECT_FALSE(stream->flow_controller()->IsEnabled()); |
} |
+TEST_P(QuicSessionTest, TooManyUnfinishedStreamsCauseConnectionClose) { |
+ if (version() < QUIC_VERSION_18) { |
+ return; |
+ } |
+ // If a buggy/malicious peer creates too many streams that are not ended with |
+ // a FIN or RST then we send a connection close. |
+ ValueRestore<bool> old_flag(&FLAGS_close_quic_connection_unfinished_streams, |
+ true); |
+ |
+ EXPECT_CALL(*connection_, |
+ SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS)).Times(1); |
+ |
+ const int kMaxStreams = 5; |
+ QuicSessionPeer::SetMaxOpenStreams(&session_, kMaxStreams); |
+ |
+ // Create kMaxStreams + 1 data streams, and close them all without receiving a |
+ // FIN or a RST from the client. |
+ const int kFirstStreamId = kClientDataStreamId1; |
+ const int kFinalStreamId = kClientDataStreamId1 + 2 * kMaxStreams + 1; |
+ for (int i = kFirstStreamId; i < kFinalStreamId; i += 2) { |
+ QuicStreamFrame data1(i, false, 0, MakeIOVector("HT")); |
+ vector<QuicStreamFrame> frames; |
+ frames.push_back(data1); |
+ session_.OnStreamFrames(frames); |
+ EXPECT_EQ(1u, session_.GetNumOpenStreams()); |
+ session_.CloseStream(i); |
+ } |
+} |
+ |
} // namespace |
} // namespace test |
} // namespace net |