Close connection on QPACK encoder or decoder stream errors. gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99. PiperOrigin-RevId: 268434745 Change-Id: Ie69e360cacd7b431373fddf1e5221304ec522000
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index 53ec3cc..a2bb509 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -402,18 +402,22 @@ 2 * max_inbound_header_list_size_); } -void QuicSpdySession::OnDecoderStreamError(QuicStringPiece /*error_message*/) { +void QuicSpdySession::OnDecoderStreamError(QuicStringPiece error_message) { DCHECK(VersionUsesQpack(transport_version())); - // TODO(112770235): Signal connection error on decoder stream errors. - QUIC_NOTREACHED(); + // TODO(b/124216424): Use HTTP_QPACK_DECODER_STREAM_ERROR. + CloseConnectionWithDetails( + QUIC_DECOMPRESSION_FAILURE, + QuicStrCat("Decoder stream error: ", error_message)); } -void QuicSpdySession::OnEncoderStreamError(QuicStringPiece /*error_message*/) { +void QuicSpdySession::OnEncoderStreamError(QuicStringPiece error_message) { DCHECK(VersionUsesQpack(transport_version())); - // TODO(112770235): Signal connection error on encoder stream errors. - QUIC_NOTREACHED(); + // TODO(b/124216424): Use HTTP_QPACK_ENCODER_STREAM_ERROR. + CloseConnectionWithDetails( + QUIC_DECOMPRESSION_FAILURE, + QuicStrCat("Encoder stream error: ", error_message)); } void QuicSpdySession::OnStreamHeadersPriority(
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index e5d50b2..f5bab97 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -2473,6 +2473,48 @@ "Received a duplicate QPACK decoder stream: Closing connection."); } +TEST_P(QuicSpdySessionTestClient, EncoderStreamError) { + if (!VersionUsesQpack(transport_version())) { + return; + } + + std::string data = QuicTextUtils::HexDecode( + "02" // Encoder stream. + "00"); // Duplicate entry 0, but no entries exist. + + QuicStreamId stream_id = + GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0); + + QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0, data); + + EXPECT_CALL( + *connection_, + CloseConnection(QUIC_DECOMPRESSION_FAILURE, + "Encoder stream error: Invalid relative index.", _)); + session_.OnStreamFrame(frame); +} + +TEST_P(QuicSpdySessionTestClient, DecoderStreamError) { + if (!VersionUsesQpack(transport_version())) { + return; + } + + std::string data = QuicTextUtils::HexDecode( + "03" // Decoder stream. + "00"); // Insert Count Increment with forbidden increment value of zero. + + QuicStreamId stream_id = + GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0); + + QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0, data); + + EXPECT_CALL( + *connection_, + CloseConnection(QUIC_DECOMPRESSION_FAILURE, + "Decoder stream error: Invalid increment value 0.", _)); + session_.OnStreamFrame(frame); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/tools/quic_simple_client_session.cc b/quic/tools/quic_simple_client_session.cc index b7743f8..f39d8fa 100644 --- a/quic/tools/quic_simple_client_session.cc +++ b/quic/tools/quic_simple_client_session.cc
@@ -8,6 +8,27 @@ namespace quic { +QuicSimpleClientSession::QuicSimpleClientSession( + const QuicConfig& config, + const ParsedQuicVersionVector& supported_versions, + QuicConnection* connection, + const QuicServerId& server_id, + QuicCryptoClientConfig* crypto_config, + QuicClientPushPromiseIndex* push_promise_index, + bool drop_response_body) + : QuicSpdyClientSession(config, + supported_versions, + connection, + server_id, + crypto_config, + push_promise_index), + drop_response_body_(drop_response_body) { + // Do not use the QPACK dynamic table in tests to avoid flakiness due to the + // uncertain order of receiving the SETTINGS frame and sending headers. + set_qpack_maximum_dynamic_table_capacity(0); + set_qpack_maximum_blocked_streams(0); +} + std::unique_ptr<QuicSpdyClientStream> QuicSimpleClientSession::CreateClientStream() { return std::make_unique<QuicSimpleClientStream>(
diff --git a/quic/tools/quic_simple_client_session.h b/quic/tools/quic_simple_client_session.h index 1a17f3d..0ebca98 100644 --- a/quic/tools/quic_simple_client_session.h +++ b/quic/tools/quic_simple_client_session.h
@@ -18,14 +18,7 @@ const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config, QuicClientPushPromiseIndex* push_promise_index, - bool drop_response_body) - : QuicSpdyClientSession(config, - supported_versions, - connection, - server_id, - crypto_config, - push_promise_index), - drop_response_body_(drop_response_body) {} + bool drop_response_body); std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override;
diff --git a/quic/tools/quic_simple_server_session.cc b/quic/tools/quic_simple_server_session.cc index 8298122..1a03ab5 100644 --- a/quic/tools/quic_simple_server_session.cc +++ b/quic/tools/quic_simple_server_session.cc
@@ -36,6 +36,11 @@ QuicUtils::GetInvalidStreamId(connection->transport_version())), quic_simple_server_backend_(quic_simple_server_backend) { DCHECK(quic_simple_server_backend_); + + // Do not use the QPACK dynamic table in tests to avoid flakiness due to the + // uncertain order of receiving the SETTINGS frame and sending headers. + set_qpack_maximum_dynamic_table_capacity(0); + set_qpack_maximum_blocked_streams(0); } QuicSimpleServerSession::~QuicSimpleServerSession() {