Uses the new `HpackEncoder` dynamic table upper bound added in a previous commit.
This will only affect behavior for users who set `OgHttp2Session::Options::max_hpack_encoding_table_capacity`.
This should fix https://github.com/envoyproxy/envoy/issues/38689.
Protected by does not affect the GFE2 binary; not protected.
PiperOrigin-RevId: 757879310
diff --git a/quiche/http2/adapter/oghttp2_session.cc b/quiche/http2/adapter/oghttp2_session.cc
index 2a5ec62..c25b291 100644
--- a/quiche/http2/adapter/oghttp2_session.cc
+++ b/quiche/http2/adapter/oghttp2_session.cc
@@ -187,13 +187,6 @@
return status.size() == 3 && status[0] == '1';
}
-// Returns the upper bound on HPACK encoder table capacity. If not specified in
-// the Options, a reasonable default upper bound is used.
-uint32_t HpackCapacityBound(const OgHttp2Session::Options& o) {
- return o.max_hpack_encoding_table_capacity.value_or(
- kMaximumHpackTableCapacity);
-}
-
bool IsNonAckSettings(const spdy::SpdyFrameIR& frame) {
return frame.frame_type() == spdy::SpdyFrameType::SETTINGS &&
!reinterpret_cast<const SpdySettingsIR&>(frame).is_ack();
@@ -381,7 +374,7 @@
max_outbound_concurrent_streams_(
options.remote_max_concurrent_streams.value_or(100u)) {
decoder_.set_visitor(&receive_logger_);
- if (options_.max_header_list_bytes) {
+ if (options_.max_header_list_bytes.has_value()) {
// Limit buffering of encoded HPACK data to 2x the decoded limit.
decoder_.GetHpackDecoder().set_max_decode_buffer_size_bytes(
2 * *options_.max_header_list_bytes);
@@ -389,9 +382,9 @@
decoder_.GetHpackDecoder().set_max_header_block_bytes(
4 * *options_.max_header_list_bytes);
}
- if (IsServerSession()) {
- remaining_preface_ = {spdy::kHttp2ConnectionHeaderPrefix,
- spdy::kHttp2ConnectionHeaderPrefixSize};
+ if (options_.max_hpack_encoding_table_capacity.has_value()) {
+ framer_.GetHpackEncoder()->SetHeaderTableSizeBound(
+ *options_.max_hpack_encoding_table_capacity);
}
if (options_.max_header_field_size.has_value()) {
headers_handler_.SetMaxFieldSize(*options_.max_header_field_size);
@@ -402,6 +395,10 @@
// endpoints don't properly handle multiple `Cookie` header fields.
framer_.GetHpackEncoder()->DisableCookieCrumbling();
}
+ if (IsServerSession()) {
+ remaining_preface_ = {spdy::kHttp2ConnectionHeaderPrefix,
+ spdy::kHttp2ConnectionHeaderPrefixSize};
+ }
}
OgHttp2Session::~OgHttp2Session() {}
@@ -1309,7 +1306,7 @@
void OgHttp2Session::OnSetting(spdy::SpdySettingsId id, uint32_t value) {
switch (id) {
case HEADER_TABLE_SIZE:
- value = std::min(value, HpackCapacityBound(options_));
+ value = std::min(value, kMaximumHpackTableCapacity);
if (value < framer_.GetHpackEncoder()->CurrentHeaderTableSizeSetting()) {
// Safe to apply a smaller table capacity immediately.
QUICHE_VLOG(3) << TracePerspectiveAsString(options_.perspective)
diff --git a/quiche/http2/adapter/oghttp2_session_test.cc b/quiche/http2/adapter/oghttp2_session_test.cc
index 58da30e..34a387b 100644
--- a/quiche/http2/adapter/oghttp2_session_test.cc
+++ b/quiche/http2/adapter/oghttp2_session_test.cc
@@ -395,8 +395,8 @@
true, nullptr);
int result = session.Send();
ASSERT_EQ(result, 0);
- // BUG: the encoder table size should not have grown beyond zero.
- EXPECT_LT(0, session.GetHpackEncoderDynamicTableSize());
+ // The encoder table size should not have grown beyond zero.
+ EXPECT_EQ(session.GetHpackEncoderDynamicTableSize(), 0);
}
TEST(OgHttp2SessionTest, ClientSubmitRequestWithLargePayload) {
@@ -801,6 +801,32 @@
EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
}
+// Demonstrates that the dynamic table size setting interpreted from the peer
+// won't exceed the hardcoded 64kB upper bound.
+TEST(OgHttp2SessionTest, ServerDynamicTableSizeAboveUpperBound) {
+ TestVisitor visitor;
+ OgHttp2Session::Options options;
+ options.perspective = Perspective::kServer;
+ OgHttp2Session session(visitor, options);
+
+ const std::string frames =
+ TestFrameSequence()
+ .ClientPreface({{HEADER_TABLE_SIZE, 100u * 1024u}})
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ // Although the peer adverised 100kB, the server interprets the setting value
+ // with a 64kB upper bound.
+ EXPECT_CALL(visitor, OnSetting(Http2Setting{HEADER_TABLE_SIZE, 64u * 1024u}));
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ const int64_t result = session.ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), static_cast<size_t>(result));
+}
+
TEST(OgHttp2SessionTest, ServerSubmitResponse) {
TestVisitor visitor;
OgHttp2Session::Options options;