Signal error if Insert Count Increment causes overflow.
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 274830568
Change-Id: Ic9e7fa84e04808d2c7bade54ed3670b53b5bb0f6
diff --git a/quic/core/qpack/qpack_blocking_manager.cc b/quic/core/qpack/qpack_blocking_manager.cc
index 2243c90..ffec172 100644
--- a/quic/core/qpack/qpack_blocking_manager.cc
+++ b/quic/core/qpack/qpack_blocking_manager.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h"
+#include <limits>
#include <utility>
namespace quic {
@@ -49,8 +50,14 @@
header_blocks_.erase(it);
}
-void QpackBlockingManager::OnInsertCountIncrement(uint64_t increment) {
+bool QpackBlockingManager::OnInsertCountIncrement(uint64_t increment) {
+ if (increment >
+ std::numeric_limits<uint64_t>::max() - known_received_count_) {
+ return false;
+ }
+
IncreaseKnownReceivedCountTo(known_received_count_ + increment);
+ return true;
}
void QpackBlockingManager::OnHeaderBlockSent(QuicStreamId stream_id,
diff --git a/quic/core/qpack/qpack_blocking_manager.h b/quic/core/qpack/qpack_blocking_manager.h
index 6bebf5f..60f7db7 100644
--- a/quic/core/qpack/qpack_blocking_manager.h
+++ b/quic/core/qpack/qpack_blocking_manager.h
@@ -40,8 +40,9 @@
void OnStreamCancellation(QuicStreamId stream_id);
// Called when an Insert Count Increment instruction is received on the
- // decoder stream.
- void OnInsertCountIncrement(uint64_t increment);
+ // decoder stream. Returns true if Known Received Count is successfully
+ // updated. Returns false on overflow.
+ bool OnInsertCountIncrement(uint64_t increment);
// Called when sending a header block containing references to dynamic table
// entries with |indices|. |indices| must not be empty.
diff --git a/quic/core/qpack/qpack_blocking_manager_test.cc b/quic/core/qpack/qpack_blocking_manager_test.cc
index 8257363..64bfb97 100644
--- a/quic/core/qpack/qpack_blocking_manager_test.cc
+++ b/quic/core/qpack/qpack_blocking_manager_test.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h"
+#include <limits>
+
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
@@ -53,7 +55,7 @@
}
TEST_F(QpackBlockingManagerTest, NotBlockedByInsertCountIncrement) {
- manager_.OnInsertCountIncrement(2);
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
// Stream 0 is not blocked, because it only references entries that are
// already acknowledged by an Insert Count Increment instruction.
@@ -65,7 +67,7 @@
manager_.OnHeaderBlockSent(0, {1, 0});
EXPECT_TRUE(stream_is_blocked(0));
- manager_.OnInsertCountIncrement(2);
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
EXPECT_FALSE(stream_is_blocked(0));
}
@@ -114,7 +116,7 @@
EXPECT_EQ(2u, manager_.known_received_count());
// Insert Count Increment increases Known Received Count.
- manager_.OnInsertCountIncrement(2);
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
EXPECT_EQ(4u, manager_.known_received_count());
EXPECT_TRUE(manager_.OnHeaderAcknowledgement(2));
@@ -161,7 +163,7 @@
EXPECT_EQ(1u, manager_.smallest_blocking_index());
// Insert Count Increment does not change smallest blocking index.
- manager_.OnInsertCountIncrement(2);
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
EXPECT_EQ(1u, manager_.smallest_blocking_index());
manager_.OnStreamCancellation(1);
@@ -249,7 +251,7 @@
EXPECT_EQ(0u, manager_.smallest_blocking_index());
// Acknowledging entry 1 still leaves one unacknowledged reference to entry 0.
- manager_.OnInsertCountIncrement(2);
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
EXPECT_EQ(2u, manager_.known_received_count());
EXPECT_EQ(0u, manager_.smallest_blocking_index());
@@ -261,13 +263,13 @@
EXPECT_EQ(0u, manager_.smallest_blocking_index());
// Acknowledging entry 2 removes last reference to entry 0.
- manager_.OnInsertCountIncrement(1);
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(1));
EXPECT_EQ(3u, manager_.known_received_count());
EXPECT_EQ(2u, manager_.smallest_blocking_index());
// Acknowledging entry 4 (and implicitly 3) removes reference to entry 2.
- manager_.OnInsertCountIncrement(2);
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
EXPECT_EQ(5u, manager_.known_received_count());
EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
@@ -386,6 +388,14 @@
EXPECT_TRUE(manager_.blocking_allowed_on_stream(kStreamId2, 1));
}
+TEST_F(QpackBlockingManagerTest, InsertCountIncrementOverflow) {
+ EXPECT_TRUE(manager_.OnInsertCountIncrement(10));
+ EXPECT_EQ(10u, manager_.known_received_count());
+
+ EXPECT_FALSE(manager_.OnInsertCountIncrement(
+ std::numeric_limits<uint64_t>::max() - 5));
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/qpack/qpack_encoder.cc b/quic/core/qpack/qpack_encoder.cc
index 418af8c..319af82 100644
--- a/quic/core/qpack/qpack_encoder.cc
+++ b/quic/core/qpack/qpack_encoder.cc
@@ -406,7 +406,10 @@
return;
}
- blocking_manager_.OnInsertCountIncrement(increment);
+ if (!blocking_manager_.OnInsertCountIncrement(increment)) {
+ decoder_stream_error_delegate_->OnDecoderStreamError(
+ "Insert Count Increment instruction causes overflow.");
+ }
if (blocking_manager_.known_received_count() >
header_table_.inserted_entry_count()) {
diff --git a/quic/core/qpack/qpack_encoder_test.cc b/quic/core/qpack/qpack_encoder_test.cc
index 3bc5859..6f2efe3 100644
--- a/quic/core/qpack/qpack_encoder_test.cc
+++ b/quic/core/qpack/qpack_encoder_test.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
+#include <limits>
#include <string>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
@@ -176,6 +177,27 @@
encoder_.OnInsertCountIncrement(1);
}
+// Regression test for https://crbug.com/1014372.
+TEST_F(QpackEncoderTest, InsertCountIncrementOverflow) {
+ QpackHeaderTable* header_table = QpackEncoderPeer::header_table(&encoder_);
+
+ // Set dynamic table capacity large enough to hold one entry.
+ header_table->SetMaximumDynamicTableCapacity(4096);
+ header_table->SetDynamicTableCapacity(4096);
+ // Insert one entry into the header table.
+ header_table->InsertEntry("foo", "bar");
+
+ // Receive Insert Count Increment instruction with increment value 1.
+ encoder_.OnInsertCountIncrement(1);
+
+ // Receive Insert Count Increment instruction that overflows the known
+ // received count. This must result in an error instead of a crash.
+ EXPECT_CALL(decoder_stream_error_delegate_,
+ OnDecoderStreamError(
+ Eq("Insert Count Increment instruction causes overflow.")));
+ encoder_.OnInsertCountIncrement(std::numeric_limits<uint64_t>::max());
+}
+
TEST_F(QpackEncoderTest, InvalidHeaderAcknowledgement) {
// Encoder receives header acknowledgement for a stream on which no header
// block with dynamic table entries was ever sent.