Allow HttpDecoder visitor to return bool upon receiving HTTP/3 frames.
The prevents decoder from reading after the stream has already freed its
sequencer.
gfe-relnote: Version 99 only. Not in prod.
PiperOrigin-RevId: 251257525
Change-Id: Ia2bd1cc0073d45df60b91dc4fcfed327b31ec369
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index 7c423b4..7ecbbf5 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -1863,6 +1863,63 @@
EXPECT_EQ("some data", data);
}
+TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
+ // The test stream will receive a stream frame containing malformed headers
+ // and normal body. Make sure the http decoder stops processing body after the
+ // connection shuts down.
+ testing::InSequence s;
+ if (!VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+
+ // Random bad headers.
+ std::string headers_frame_payload =
+ QuicTextUtils::HexDecode("00002a94e7036261");
+ std::unique_ptr<char[]> headers_buffer;
+ QuicByteCount headers_frame_header_length =
+ encoder_.SerializeHeadersFrameHeader(headers_frame_payload.length(),
+ &headers_buffer);
+ QuicStringPiece headers_frame_header(headers_buffer.get(),
+ headers_frame_header_length);
+
+ std::string data_frame_payload = "some data";
+ std::unique_ptr<char[]> data_buffer;
+ QuicByteCount data_frame_header_length = encoder_.SerializeDataFrameHeader(
+ data_frame_payload.length(), &data_buffer);
+ QuicStringPiece data_frame_header(data_buffer.get(),
+ data_frame_header_length);
+
+ std::string stream_frame_payload =
+ QuicStrCat(headers_frame_header, headers_frame_payload, data_frame_header,
+ data_frame_payload);
+ QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
+
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_DECOMPRESSION_FAILURE,
+ "Error decompressing header block on stream 4: "
+ "Incomplete header block.",
+ _))
+ .WillOnce(
+ (Invoke([this](QuicErrorCode error, const std::string& error_details,
+ ConnectionCloseBehavior connection_close_behavior) {
+ connection_->ReallyCloseConnection(error, error_details,
+ connection_close_behavior);
+ })));
+ EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
+ EXPECT_CALL(*session_, OnConnectionClosed(_, _, _))
+ .WillOnce(
+ Invoke([this](QuicErrorCode error, const std::string& error_details,
+ ConnectionCloseSource source) {
+ session_->ReallyOnConnectionClosed(error, error_details, source);
+ }));
+ EXPECT_CALL(*session_, SendRstStream(_, _, _));
+ EXPECT_CALL(*session_, SendRstStream(_, _, _));
+ stream_->OnStreamFrame(frame);
+}
+
} // namespace
} // namespace test
} // namespace quic