Small follow-on to handle header-related errors earlier.
I missed a couple of places. This also fixes //third_party/http2/adapter:oghttp2_adapter_test in QUICHE and embedders.
PiperOrigin-RevId: 621883995
diff --git a/quiche/http2/adapter/nghttp2_adapter_test.cc b/quiche/http2/adapter/nghttp2_adapter_test.cc
index da96aa9..5b07a48 100644
--- a/quiche/http2/adapter/nghttp2_adapter_test.cc
+++ b/quiche/http2/adapter/nghttp2_adapter_test.cc
@@ -3840,6 +3840,64 @@
SpdyFrameType::PING}));
}
+TEST(NgHttp2AdapterTest, ServerVisitorRejectsHeaders) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ EXPECT_FALSE(adapter->want_write());
+
+ const std::string frames =
+ TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"},
+ {"header1", "ok"},
+ {"header2", "rejected"},
+ {"header3", "not processed"}, // CONTINUATION starts here
+ {"header4", "not processed"},
+ {"header5", "not processed"},
+ {"header6", "not processed"},
+ {"header7", "not processed"},
+ {"header8", "not processed"}},
+ /*fin=*/false, /*add_continuation=*/true)
+ .Serialize();
+
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x0));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(5);
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "header2", _))
+ .WillOnce(testing::Return(Http2VisitorInterface::HEADER_RST_STREAM));
+ // The CONTINUATION frame header and header fields are not processed.
+
+ int64_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(static_cast<size_t>(result), frames.size());
+
+ EXPECT_TRUE(adapter->want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
+ EXPECT_CALL(visitor,
+ OnFrameSent(RST_STREAM, 1, _, 0x0,
+ static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::INTERNAL_ERROR));
+
+ int send_result = adapter->Send();
+ // Some bytes should have been serialized.
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
+ SpdyFrameType::RST_STREAM}));
+}
+
TEST(OgHttp2AdapterTest, HeaderValuesWithObsTextAllowed) {
DataSavingVisitor visitor;
auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
diff --git a/quiche/http2/adapter/oghttp2_session.cc b/quiche/http2/adapter/oghttp2_session.cc
index 219c07b..235b0fa 100644
--- a/quiche/http2/adapter/oghttp2_session.cc
+++ b/quiche/http2/adapter/oghttp2_session.cc
@@ -279,6 +279,7 @@
StatusIs1xx(status_header())) {
QUICHE_VLOG(1) << "Unexpected end of stream without final headers";
SetResult(Http2VisitorInterface::HEADER_HTTP_MESSAGING);
+ return;
}
const bool result = visitor_.OnEndHeadersForStream(stream_id_);
if (!result) {