Close connection on incoming PRIORITY_UPDATE frame with invalid stream ID.
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 290870791
Change-Id: Ie618cfe2479ae1f7f0151b0bc03a939aec9e87b6
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index 301e1d1..db93a86 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -504,7 +504,19 @@
return true;
}
- // TODO(b/147306124): Signal error on invalid stream_id.
+ QuicStreamCount advertised_max_incoming_bidirectional_streams =
+ GetAdvertisedMaxIncomingBidirectionalStreams();
+ if (advertised_max_incoming_bidirectional_streams == 0 ||
+ stream_id > QuicUtils::GetFirstBidirectionalStreamId(
+ transport_version(), Perspective::IS_CLIENT) +
+ QuicUtils::StreamIdDelta(transport_version()) *
+ (advertised_max_incoming_bidirectional_streams - 1)) {
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID,
+ "PRIORITY_UPDATE frame received for invalid stream.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
MaybeSetStreamPriority(stream_id, spdy::SpdyStreamPrecedence(urgency));
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 5f3ea29..16ec7b6 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -1509,6 +1509,12 @@
GetNumOpenOutgoingStreams());
}
+QuicStreamCount QuicSession::GetAdvertisedMaxIncomingBidirectionalStreams()
+ const {
+ DCHECK(VersionHasIetfQuicFrames(transport_version()));
+ return v99_streamid_manager_.advertised_max_incoming_bidirectional_streams();
+}
+
QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
DCHECK(!QuicContainsKey(pending_stream_map_, stream_id));
if (QuicUtils::IsCryptoStreamId(transport_version(), stream_id)) {
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index f473156..84ba8e1 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -544,6 +544,10 @@
// Returns the number of open dynamic streams.
uint64_t GetNumOpenDynamicStreams() const;
+ // Returns the maximum bidirectional streams parameter sent with the handshake
+ // as a transport parameter, or in the most recent MAX_STREAMS frame.
+ QuicStreamCount GetAdvertisedMaxIncomingBidirectionalStreams() const;
+
// Performs the work required to close |stream_id|. If |locally_reset|
// then the stream has been reset by this endpoint, not by the peer.
virtual void CloseStreamInner(QuicStreamId stream_id, bool locally_reset);