1 // Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/qpack/qpack_decoder.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "absl/strings/escaping.h"
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/platform/api/quic_flags.h"
13 #include "quiche/quic/platform/api/quic_logging.h"
14 #include "quiche/quic/platform/api/quic_test.h"
15 #include "quiche/quic/test_tools/qpack/qpack_decoder_test_utils.h"
16 #include "quiche/quic/test_tools/qpack/qpack_test_utils.h"
17
18 using ::testing::_;
19 using ::testing::Eq;
20 using ::testing::Invoke;
21 using ::testing::Mock;
22 using ::testing::Sequence;
23 using ::testing::StrictMock;
24 using ::testing::Values;
25
26 namespace quic {
27 namespace test {
28 namespace {
29
30 // Header Acknowledgement decoder stream instruction with stream_id = 1.
31 const char* const kHeaderAcknowledgement = "\x81";
32
33 const uint64_t kMaximumDynamicTableCapacity = 1024;
34 const uint64_t kMaximumBlockedStreams = 1;
35
36 class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
37 protected:
QpackDecoderTest()38 QpackDecoderTest()
39 : qpack_decoder_(kMaximumDynamicTableCapacity, kMaximumBlockedStreams,
40 &encoder_stream_error_delegate_),
41 fragment_mode_(GetParam()) {
42 qpack_decoder_.set_qpack_stream_sender_delegate(
43 &decoder_stream_sender_delegate_);
44 }
45
46 ~QpackDecoderTest() override = default;
47
SetUp()48 void SetUp() override {
49 // Destroy QpackProgressiveDecoder on error to test that it does not crash.
50 // See https://crbug.com/1025209.
51 ON_CALL(handler_, OnDecodingErrorDetected(_, _))
52 .WillByDefault(Invoke([this](QuicErrorCode /* error_code */,
53 absl::string_view /* error_message */) {
54 progressive_decoder_.reset();
55 }));
56 }
57
DecodeEncoderStreamData(absl::string_view data)58 void DecodeEncoderStreamData(absl::string_view data) {
59 qpack_decoder_.encoder_stream_receiver()->Decode(data);
60 }
61
CreateProgressiveDecoder(QuicStreamId stream_id)62 std::unique_ptr<QpackProgressiveDecoder> CreateProgressiveDecoder(
63 QuicStreamId stream_id) {
64 return qpack_decoder_.CreateProgressiveDecoder(stream_id, &handler_);
65 }
66
FlushDecoderStream()67 void FlushDecoderStream() { qpack_decoder_.FlushDecoderStream(); }
68
69 // Set up |progressive_decoder_|.
StartDecoding()70 void StartDecoding() {
71 progressive_decoder_ = CreateProgressiveDecoder(/* stream_id = */ 1);
72 }
73
74 // Pass header block data to QpackProgressiveDecoder::Decode()
75 // in fragments dictated by |fragment_mode_|.
DecodeData(absl::string_view data)76 void DecodeData(absl::string_view data) {
77 auto fragment_size_generator =
78 FragmentModeToFragmentSizeGenerator(fragment_mode_);
79 while (progressive_decoder_ && !data.empty()) {
80 size_t fragment_size = std::min(fragment_size_generator(), data.size());
81 progressive_decoder_->Decode(data.substr(0, fragment_size));
82 data = data.substr(fragment_size);
83 }
84 }
85
86 // Signal end of header block to QpackProgressiveDecoder.
EndDecoding()87 void EndDecoding() {
88 if (progressive_decoder_) {
89 progressive_decoder_->EndHeaderBlock();
90 }
91 // If no error was detected, |*progressive_decoder_| is kept alive so that
92 // it can handle callbacks later in case of blocked decoding.
93 }
94
95 // Decode an entire header block.
DecodeHeaderBlock(absl::string_view data)96 void DecodeHeaderBlock(absl::string_view data) {
97 StartDecoding();
98 DecodeData(data);
99 EndDecoding();
100 }
101
102 StrictMock<MockEncoderStreamErrorDelegate> encoder_stream_error_delegate_;
103 StrictMock<MockQpackStreamSenderDelegate> decoder_stream_sender_delegate_;
104 StrictMock<MockHeadersHandler> handler_;
105
106 private:
107 QpackDecoder qpack_decoder_;
108 const FragmentMode fragment_mode_;
109 std::unique_ptr<QpackProgressiveDecoder> progressive_decoder_;
110 };
111
112 INSTANTIATE_TEST_SUITE_P(All, QpackDecoderTest,
113 Values(FragmentMode::kSingleChunk,
114 FragmentMode::kOctetByOctet));
115
TEST_P(QpackDecoderTest,NoPrefix)116 TEST_P(QpackDecoderTest, NoPrefix) {
117 EXPECT_CALL(handler_,
118 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
119 Eq("Incomplete header data prefix.")));
120
121 // Header Data Prefix is at least two bytes long.
122 std::string input;
123 ASSERT_TRUE(absl::HexStringToBytes("00", &input));
124 DecodeHeaderBlock(input);
125 }
126
127 // Regression test for https://1025209: QpackProgressiveDecoder must not crash
128 // in Decode() if it is destroyed by handler_.OnDecodingErrorDetected().
TEST_P(QpackDecoderTest,InvalidPrefix)129 TEST_P(QpackDecoderTest, InvalidPrefix) {
130 StartDecoding();
131
132 EXPECT_CALL(handler_,
133 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
134 Eq("Encoded integer too large.")));
135
136 // Encoded Required Insert Count in Header Data Prefix is too large.
137 std::string input;
138 ASSERT_TRUE(absl::HexStringToBytes("ffffffffffffffffffffffffffff", &input));
139 DecodeData(input);
140 }
141
TEST_P(QpackDecoderTest,EmptyHeaderBlock)142 TEST_P(QpackDecoderTest, EmptyHeaderBlock) {
143 EXPECT_CALL(handler_, OnDecodingCompleted());
144
145 std::string input;
146 ASSERT_TRUE(absl::HexStringToBytes("0000", &input));
147 DecodeHeaderBlock(input);
148 }
149
TEST_P(QpackDecoderTest,LiteralEntryEmptyName)150 TEST_P(QpackDecoderTest, LiteralEntryEmptyName) {
151 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("foo")));
152 EXPECT_CALL(handler_, OnDecodingCompleted());
153
154 std::string input;
155 ASSERT_TRUE(absl::HexStringToBytes("00002003666f6f", &input));
156 DecodeHeaderBlock(input);
157 }
158
TEST_P(QpackDecoderTest,LiteralEntryEmptyValue)159 TEST_P(QpackDecoderTest, LiteralEntryEmptyValue) {
160 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
161 EXPECT_CALL(handler_, OnDecodingCompleted());
162
163 std::string input;
164 ASSERT_TRUE(absl::HexStringToBytes("000023666f6f00", &input));
165 DecodeHeaderBlock(input);
166 }
167
TEST_P(QpackDecoderTest,LiteralEntryEmptyNameAndValue)168 TEST_P(QpackDecoderTest, LiteralEntryEmptyNameAndValue) {
169 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("")));
170 EXPECT_CALL(handler_, OnDecodingCompleted());
171
172 std::string input;
173 ASSERT_TRUE(absl::HexStringToBytes("00002000", &input));
174 DecodeHeaderBlock(input);
175 }
176
TEST_P(QpackDecoderTest,SimpleLiteralEntry)177 TEST_P(QpackDecoderTest, SimpleLiteralEntry) {
178 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
179 EXPECT_CALL(handler_, OnDecodingCompleted());
180
181 std::string input;
182 ASSERT_TRUE(absl::HexStringToBytes("000023666f6f03626172", &input));
183 DecodeHeaderBlock(input);
184 }
185
TEST_P(QpackDecoderTest,MultipleLiteralEntries)186 TEST_P(QpackDecoderTest, MultipleLiteralEntries) {
187 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
188 std::string str(127, 'a');
189 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foobaar"), absl::string_view(str)));
190 EXPECT_CALL(handler_, OnDecodingCompleted());
191
192 std::string input;
193 ASSERT_TRUE(absl::HexStringToBytes(
194 "0000" // prefix
195 "23666f6f03626172" // foo: bar
196 "2700666f6f62616172" // 7 octet long header name, the smallest number
197 // that does not fit on a 3-bit prefix.
198 "7f0061616161616161" // 127 octet long header value, the smallest number
199 "616161616161616161" // that does not fit on a 7-bit prefix.
200 "6161616161616161616161616161616161616161616161616161616161616161616161"
201 "6161616161616161616161616161616161616161616161616161616161616161616161"
202 "6161616161616161616161616161616161616161616161616161616161616161616161"
203 "616161616161",
204 &input));
205 DecodeHeaderBlock(input);
206 }
207
208 // Name Length value is too large for varint decoder to decode.
TEST_P(QpackDecoderTest,NameLenTooLargeForVarintDecoder)209 TEST_P(QpackDecoderTest, NameLenTooLargeForVarintDecoder) {
210 EXPECT_CALL(handler_,
211 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
212 Eq("Encoded integer too large.")));
213
214 std::string input;
215 ASSERT_TRUE(absl::HexStringToBytes("000027ffffffffffffffffffff", &input));
216 DecodeHeaderBlock(input);
217 }
218
219 // Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_P(QpackDecoderTest,NameLenExceedsLimit)220 TEST_P(QpackDecoderTest, NameLenExceedsLimit) {
221 EXPECT_CALL(handler_,
222 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
223 Eq("String literal too long.")));
224
225 std::string input;
226 ASSERT_TRUE(absl::HexStringToBytes("000027ffff7f", &input));
227 DecodeHeaderBlock(input);
228 }
229
230 // Value Length value is too large for varint decoder to decode.
TEST_P(QpackDecoderTest,ValueLenTooLargeForVarintDecoder)231 TEST_P(QpackDecoderTest, ValueLenTooLargeForVarintDecoder) {
232 EXPECT_CALL(handler_,
233 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
234 Eq("Encoded integer too large.")));
235
236 std::string input;
237 ASSERT_TRUE(
238 absl::HexStringToBytes("000023666f6f7fffffffffffffffffffff", &input));
239 DecodeHeaderBlock(input);
240 }
241
242 // Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_P(QpackDecoderTest,ValueLenExceedsLimit)243 TEST_P(QpackDecoderTest, ValueLenExceedsLimit) {
244 EXPECT_CALL(handler_,
245 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
246 Eq("String literal too long.")));
247
248 std::string input;
249 ASSERT_TRUE(absl::HexStringToBytes("000023666f6f7fffff7f", &input));
250 DecodeHeaderBlock(input);
251 }
252
TEST_P(QpackDecoderTest,LineFeedInValue)253 TEST_P(QpackDecoderTest, LineFeedInValue) {
254 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ba\nr")));
255 EXPECT_CALL(handler_, OnDecodingCompleted());
256
257 std::string input;
258 ASSERT_TRUE(absl::HexStringToBytes("000023666f6f0462610a72", &input));
259 DecodeHeaderBlock(input);
260 }
261
TEST_P(QpackDecoderTest,IncompleteHeaderBlock)262 TEST_P(QpackDecoderTest, IncompleteHeaderBlock) {
263 EXPECT_CALL(handler_,
264 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
265 Eq("Incomplete header block.")));
266
267 std::string input;
268 ASSERT_TRUE(absl::HexStringToBytes("00002366", &input));
269 DecodeHeaderBlock(input);
270 }
271
TEST_P(QpackDecoderTest,HuffmanSimple)272 TEST_P(QpackDecoderTest, HuffmanSimple) {
273 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value")));
274 EXPECT_CALL(handler_, OnDecodingCompleted());
275
276 std::string input;
277 ASSERT_TRUE(absl::HexStringToBytes(
278 "00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf", &input));
279 DecodeHeaderBlock(input);
280 }
281
TEST_P(QpackDecoderTest,AlternatingHuffmanNonHuffman)282 TEST_P(QpackDecoderTest, AlternatingHuffmanNonHuffman) {
283 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value")))
284 .Times(4);
285 EXPECT_CALL(handler_, OnDecodingCompleted());
286
287 std::string input;
288 ASSERT_TRUE(absl::HexStringToBytes(
289 "0000" // Prefix.
290 "2f0125a849e95ba97d7f" // Huffman-encoded name.
291 "8925a849e95bb8e8b4bf" // Huffman-encoded value.
292 "2703637573746f6d2d6b6579" // Non-Huffman encoded name.
293 "0c637573746f6d2d76616c7565" // Non-Huffman encoded value.
294 "2f0125a849e95ba97d7f" // Huffman-encoded name.
295 "0c637573746f6d2d76616c7565" // Non-Huffman encoded value.
296 "2703637573746f6d2d6b6579" // Non-Huffman encoded name.
297 "8925a849e95bb8e8b4bf", // Huffman-encoded value.
298 &input));
299 DecodeHeaderBlock(input);
300 }
301
TEST_P(QpackDecoderTest,HuffmanNameDoesNotHaveEOSPrefix)302 TEST_P(QpackDecoderTest, HuffmanNameDoesNotHaveEOSPrefix) {
303 EXPECT_CALL(handler_,
304 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
305 Eq("Error in Huffman-encoded string.")));
306
307 // 'y' ends in 0b0 on the most significant bit of the last byte.
308 // The remaining 7 bits must be a prefix of EOS, which is all 1s.
309 std::string input;
310 ASSERT_TRUE(absl::HexStringToBytes(
311 "00002f0125a849e95ba97d7e8925a849e95bb8e8b4bf", &input));
312 DecodeHeaderBlock(input);
313 }
314
TEST_P(QpackDecoderTest,HuffmanValueDoesNotHaveEOSPrefix)315 TEST_P(QpackDecoderTest, HuffmanValueDoesNotHaveEOSPrefix) {
316 EXPECT_CALL(handler_,
317 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
318 Eq("Error in Huffman-encoded string.")));
319
320 // 'e' ends in 0b101, taking up the 3 most significant bits of the last byte.
321 // The remaining 5 bits must be a prefix of EOS, which is all 1s.
322 std::string input;
323 ASSERT_TRUE(absl::HexStringToBytes(
324 "00002f0125a849e95ba97d7f8925a849e95bb8e8b4be", &input));
325 DecodeHeaderBlock(input);
326 }
327
TEST_P(QpackDecoderTest,HuffmanNameEOSPrefixTooLong)328 TEST_P(QpackDecoderTest, HuffmanNameEOSPrefixTooLong) {
329 EXPECT_CALL(handler_,
330 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
331 Eq("Error in Huffman-encoded string.")));
332
333 // The trailing EOS prefix must be at most 7 bits long. Appending one octet
334 // with value 0xff is invalid, even though 0b111111111111111 (15 bits) is a
335 // prefix of EOS.
336 std::string input;
337 ASSERT_TRUE(absl::HexStringToBytes(
338 "00002f0225a849e95ba97d7fff8925a849e95bb8e8b4bf", &input));
339 DecodeHeaderBlock(input);
340 }
341
TEST_P(QpackDecoderTest,HuffmanValueEOSPrefixTooLong)342 TEST_P(QpackDecoderTest, HuffmanValueEOSPrefixTooLong) {
343 EXPECT_CALL(handler_,
344 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
345 Eq("Error in Huffman-encoded string.")));
346
347 // The trailing EOS prefix must be at most 7 bits long. Appending one octet
348 // with value 0xff is invalid, even though 0b1111111111111 (13 bits) is a
349 // prefix of EOS.
350 std::string input;
351 ASSERT_TRUE(absl::HexStringToBytes(
352 "00002f0125a849e95ba97d7f8a25a849e95bb8e8b4bfff", &input));
353 DecodeHeaderBlock(input);
354 }
355
TEST_P(QpackDecoderTest,StaticTable)356 TEST_P(QpackDecoderTest, StaticTable) {
357 // A header name that has multiple entries with different values.
358 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
359 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("POST")));
360 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("TRACE")));
361
362 // A header name that has a single entry with non-empty value.
363 EXPECT_CALL(handler_,
364 OnHeaderDecoded(Eq("accept-encoding"), Eq("gzip, deflate, br")));
365 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq("compress")));
366 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq("")));
367
368 // A header name that has a single entry with empty value.
369 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq("")));
370 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq("foo")));
371
372 EXPECT_CALL(handler_, OnDecodingCompleted());
373
374 std::string input;
375 ASSERT_TRUE(absl::HexStringToBytes(
376 "0000d1dfccd45f108621e9aec2a11f5c8294e75f000554524143455f1000", &input));
377 DecodeHeaderBlock(input);
378 }
379
TEST_P(QpackDecoderTest,TooHighStaticTableIndex)380 TEST_P(QpackDecoderTest, TooHighStaticTableIndex) {
381 // This is the last entry in the static table with index 98.
382 EXPECT_CALL(handler_,
383 OnHeaderDecoded(Eq("x-frame-options"), Eq("sameorigin")));
384
385 // Addressing entry 99 should trigger an error.
386 EXPECT_CALL(handler_,
387 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
388 Eq("Static table entry not found.")));
389
390 std::string input;
391 ASSERT_TRUE(absl::HexStringToBytes("0000ff23ff24", &input));
392 DecodeHeaderBlock(input);
393 }
394
TEST_P(QpackDecoderTest,DynamicTable)395 TEST_P(QpackDecoderTest, DynamicTable) {
396 std::string input;
397 ASSERT_TRUE(absl::HexStringToBytes(
398 "3fe107" // Set dynamic table capacity to 1024.
399 "6294e703626172" // Add literal entry with name "foo" and value "bar".
400 "80035a5a5a" // Add entry with name of dynamic table entry index 0
401 // (relative index) and value "ZZZ".
402 "cf8294e7" // Add entry with name of static table entry index 15
403 // and value "foo".
404 "01", // Duplicate entry with relative index 1.
405 &input));
406 DecodeEncoderStreamData(input);
407
408 // Now there are four entries in the dynamic table.
409 // Entry 0: "foo", "bar"
410 // Entry 1: "foo", "ZZZ"
411 // Entry 2: ":method", "foo"
412 // Entry 3: "foo", "ZZZ"
413
414 // Use a Sequence to test that mock methods are called in order.
415 Sequence s;
416
417 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))).InSequence(s);
418 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
419 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("foo")))
420 .InSequence(s);
421 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
422 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
423 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
424 EXPECT_CALL(decoder_stream_sender_delegate_,
425 WriteStreamData(Eq(kHeaderAcknowledgement)))
426 .InSequence(s);
427 }
428 EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
429 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
430 EXPECT_CALL(decoder_stream_sender_delegate_,
431 WriteStreamData(Eq(kHeaderAcknowledgement)))
432 .InSequence(s);
433 }
434
435 ASSERT_TRUE(absl::HexStringToBytes(
436 "0500" // Required Insert Count 4 and Delta Base 0.
437 // Base is 4 + 0 = 4.
438 "83" // Dynamic table entry with relative index 3, absolute index 0.
439 "82" // Dynamic table entry with relative index 2, absolute index 1.
440 "81" // Dynamic table entry with relative index 1, absolute index 2.
441 "80" // Dynamic table entry with relative index 0, absolute index 3.
442 "41025a5a", // Name of entry 1 (relative index) from dynamic table,
443 // with value "ZZ".
444 &input));
445 DecodeHeaderBlock(input);
446 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
447 FlushDecoderStream();
448 }
449
450 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))).InSequence(s);
451 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
452 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("foo")))
453 .InSequence(s);
454 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
455 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
456 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
457 EXPECT_CALL(decoder_stream_sender_delegate_,
458 WriteStreamData(Eq(kHeaderAcknowledgement)))
459 .InSequence(s);
460 }
461 EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
462 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
463 EXPECT_CALL(decoder_stream_sender_delegate_,
464 WriteStreamData(Eq(kHeaderAcknowledgement)))
465 .InSequence(s);
466 }
467
468 ASSERT_TRUE(absl::HexStringToBytes(
469 "0502" // Required Insert Count 4 and Delta Base 2.
470 // Base is 4 + 2 = 6.
471 "85" // Dynamic table entry with relative index 5, absolute index 0.
472 "84" // Dynamic table entry with relative index 4, absolute index 1.
473 "83" // Dynamic table entry with relative index 3, absolute index 2.
474 "82" // Dynamic table entry with relative index 2, absolute index 3.
475 "43025a5a", // Name of entry 3 (relative index) from dynamic table,
476 // with value "ZZ".
477 &input));
478 DecodeHeaderBlock(input);
479 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
480 FlushDecoderStream();
481 }
482
483 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))).InSequence(s);
484 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
485 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("foo")))
486 .InSequence(s);
487 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
488 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
489 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
490 EXPECT_CALL(decoder_stream_sender_delegate_,
491 WriteStreamData(Eq(kHeaderAcknowledgement)))
492 .InSequence(s);
493 }
494 EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
495 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
496 EXPECT_CALL(decoder_stream_sender_delegate_,
497 WriteStreamData(Eq(kHeaderAcknowledgement)))
498 .InSequence(s);
499 }
500
501 ASSERT_TRUE(absl::HexStringToBytes(
502 "0582" // Required Insert Count 4 and Delta Base 2 with sign bit set.
503 // Base is 4 - 2 - 1 = 1.
504 "80" // Dynamic table entry with relative index 0, absolute index 0.
505 "10" // Dynamic table entry with post-base index 0, absolute index 1.
506 "11" // Dynamic table entry with post-base index 1, absolute index 2.
507 "12" // Dynamic table entry with post-base index 2, absolute index 3.
508 "01025a5a", // Name of entry 1 (post-base index) from dynamic table,
509 // with value "ZZ".
510 &input));
511 DecodeHeaderBlock(input);
512 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
513 FlushDecoderStream();
514 }
515 }
516
TEST_P(QpackDecoderTest,DecreasingDynamicTableCapacityEvictsEntries)517 TEST_P(QpackDecoderTest, DecreasingDynamicTableCapacityEvictsEntries) {
518 std::string input;
519 // Set dynamic table capacity to 1024.
520 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
521 DecodeEncoderStreamData(input);
522 // Add literal entry with name "foo" and value "bar".
523 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
524 DecodeEncoderStreamData(input);
525
526 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
527 EXPECT_CALL(handler_, OnDecodingCompleted());
528 EXPECT_CALL(decoder_stream_sender_delegate_,
529 WriteStreamData(Eq(kHeaderAcknowledgement)));
530
531 ASSERT_TRUE(absl::HexStringToBytes(
532 "0200" // Required Insert Count 1 and Delta Base 0.
533 // Base is 1 + 0 = 1.
534 "80", // Dynamic table entry with relative index 0, absolute index 0.
535 &input));
536 DecodeHeaderBlock(input);
537
538 // Change dynamic table capacity to 32 bytes, smaller than the entry.
539 // This must cause the entry to be evicted.
540 ASSERT_TRUE(absl::HexStringToBytes("3f01", &input));
541 DecodeEncoderStreamData(input);
542
543 EXPECT_CALL(handler_, OnDecodingErrorDetected(
544 QUIC_QPACK_DECOMPRESSION_FAILED,
545 Eq("Dynamic table entry already evicted.")));
546
547 ASSERT_TRUE(absl::HexStringToBytes(
548 "0200" // Required Insert Count 1 and Delta Base 0.
549 // Base is 1 + 0 = 1.
550 "80", // Dynamic table entry with relative index 0, absolute index 0.
551 &input));
552 DecodeHeaderBlock(input);
553 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
554 FlushDecoderStream();
555 }
556 }
557
TEST_P(QpackDecoderTest,EncoderStreamErrorEntryTooLarge)558 TEST_P(QpackDecoderTest, EncoderStreamErrorEntryTooLarge) {
559 std::string input;
560 EXPECT_CALL(
561 encoder_stream_error_delegate_,
562 OnEncoderStreamError(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_LITERAL,
563 Eq("Error inserting literal entry.")));
564
565 // Set dynamic table capacity to 34.
566 ASSERT_TRUE(absl::HexStringToBytes("3f03", &input));
567 DecodeEncoderStreamData(input);
568 // Add literal entry with name "foo" and value "bar", size is 32 + 3 + 3 = 38.
569 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
570 DecodeEncoderStreamData(input);
571 }
572
TEST_P(QpackDecoderTest,EncoderStreamErrorInvalidStaticTableEntry)573 TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidStaticTableEntry) {
574 EXPECT_CALL(
575 encoder_stream_error_delegate_,
576 OnEncoderStreamError(QUIC_QPACK_ENCODER_STREAM_INVALID_STATIC_ENTRY,
577 Eq("Invalid static table entry.")));
578
579 // Address invalid static table entry index 99.
580 std::string input;
581 ASSERT_TRUE(absl::HexStringToBytes("ff2400", &input));
582 DecodeEncoderStreamData(input);
583 }
584
TEST_P(QpackDecoderTest,EncoderStreamErrorInvalidDynamicTableEntry)585 TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidDynamicTableEntry) {
586 EXPECT_CALL(encoder_stream_error_delegate_,
587 OnEncoderStreamError(
588 QUIC_QPACK_ENCODER_STREAM_INSERTION_INVALID_RELATIVE_INDEX,
589 Eq("Invalid relative index.")));
590
591 std::string input;
592 ASSERT_TRUE(absl::HexStringToBytes(
593 "3fe107" // Set dynamic table capacity to 1024.
594 "6294e703626172" // Add literal entry with name "foo" and value "bar".
595 "8100", // Address dynamic table entry with relative index 1. Such
596 // entry does not exist. The most recently added and only
597 // dynamic table entry has relative index 0.
598 &input));
599 DecodeEncoderStreamData(input);
600 }
601
TEST_P(QpackDecoderTest,EncoderStreamErrorDuplicateInvalidEntry)602 TEST_P(QpackDecoderTest, EncoderStreamErrorDuplicateInvalidEntry) {
603 EXPECT_CALL(encoder_stream_error_delegate_,
604 OnEncoderStreamError(
605 QUIC_QPACK_ENCODER_STREAM_DUPLICATE_INVALID_RELATIVE_INDEX,
606 Eq("Invalid relative index.")));
607
608 std::string input;
609 ASSERT_TRUE(absl::HexStringToBytes(
610 "3fe107" // Set dynamic table capacity to 1024.
611 "6294e703626172" // Add literal entry with name "foo" and value "bar".
612 "01", // Duplicate dynamic table entry with relative index 1. Such
613 // entry does not exist. The most recently added and only
614 // dynamic table entry has relative index 0.
615 &input));
616 DecodeEncoderStreamData(input);
617 }
618
TEST_P(QpackDecoderTest,EncoderStreamErrorTooLargeInteger)619 TEST_P(QpackDecoderTest, EncoderStreamErrorTooLargeInteger) {
620 EXPECT_CALL(encoder_stream_error_delegate_,
621 OnEncoderStreamError(QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE,
622 Eq("Encoded integer too large.")));
623
624 std::string input;
625 ASSERT_TRUE(absl::HexStringToBytes("3fffffffffffffffffffff", &input));
626 DecodeEncoderStreamData(input);
627 }
628
TEST_P(QpackDecoderTest,InvalidDynamicEntryWhenBaseIsZero)629 TEST_P(QpackDecoderTest, InvalidDynamicEntryWhenBaseIsZero) {
630 EXPECT_CALL(handler_, OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
631 Eq("Invalid relative index.")));
632
633 std::string input;
634 // Set dynamic table capacity to 1024.
635 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
636 DecodeEncoderStreamData(input);
637 // Add literal entry with name "foo" and value "bar".
638 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
639 DecodeEncoderStreamData(input);
640
641 ASSERT_TRUE(absl::HexStringToBytes(
642 "0280" // Required Insert Count is 1. Base 1 - 1 - 0 = 0 is explicitly
643 // permitted by the spec.
644 "80", // However, addressing entry with relative index 0 would point to
645 // absolute index -1, which is invalid.
646 &input));
647 DecodeHeaderBlock(input);
648 }
649
TEST_P(QpackDecoderTest,InvalidNegativeBase)650 TEST_P(QpackDecoderTest, InvalidNegativeBase) {
651 EXPECT_CALL(handler_, OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
652 Eq("Error calculating Base.")));
653
654 // Required Insert Count 1, Delta Base 1 with sign bit set, Base would
655 // be 1 - 1 - 1 = -1, but it is not allowed to be negative.
656 std::string input;
657 ASSERT_TRUE(absl::HexStringToBytes("0281", &input));
658 DecodeHeaderBlock(input);
659 }
660
TEST_P(QpackDecoderTest,InvalidDynamicEntryByRelativeIndex)661 TEST_P(QpackDecoderTest, InvalidDynamicEntryByRelativeIndex) {
662 std::string input;
663 // Set dynamic table capacity to 1024.
664 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
665 DecodeEncoderStreamData(input);
666 // Add literal entry with name "foo" and value "bar".
667 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
668 DecodeEncoderStreamData(input);
669
670 EXPECT_CALL(handler_, OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
671 Eq("Invalid relative index.")));
672
673 ASSERT_TRUE(absl::HexStringToBytes(
674 "0200" // Required Insert Count 1 and Delta Base 0.
675 // Base is 1 + 0 = 1.
676 "81", // Indexed Header Field instruction addressing relative index 1.
677 // This is absolute index -1, which is invalid.
678 &input));
679 DecodeHeaderBlock(input);
680
681 EXPECT_CALL(handler_, OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
682 Eq("Invalid relative index.")));
683
684 ASSERT_TRUE(absl::HexStringToBytes(
685 "0200" // Required Insert Count 1 and Delta Base 0.
686 // Base is 1 + 0 = 1.
687 "4100", // Literal Header Field with Name Reference instruction
688 // addressing relative index 1. This is absolute index -1,
689 // which is invalid.
690 &input));
691 DecodeHeaderBlock(input);
692 }
693
TEST_P(QpackDecoderTest,EvictedDynamicTableEntry)694 TEST_P(QpackDecoderTest, EvictedDynamicTableEntry) {
695 std::string input;
696 // Update dynamic table capacity to 128.
697 ASSERT_TRUE(absl::HexStringToBytes("3f61", &input));
698 DecodeEncoderStreamData(input);
699
700 // Add literal entry with name "foo" and value "bar", size 32 + 3 + 3 = 38.
701 // This fits in the table three times.
702 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
703 DecodeEncoderStreamData(input);
704 // Duplicate entry four times. This evicts the first two instances.
705 ASSERT_TRUE(absl::HexStringToBytes("00000000", &input));
706 DecodeEncoderStreamData(input);
707
708 EXPECT_CALL(handler_, OnDecodingErrorDetected(
709 QUIC_QPACK_DECOMPRESSION_FAILED,
710 Eq("Dynamic table entry already evicted.")));
711
712 ASSERT_TRUE(absl::HexStringToBytes(
713 "0500" // Required Insert Count 4 and Delta Base 0.
714 // Base is 4 + 0 = 4.
715 "82", // Indexed Header Field instruction addressing relative index 2.
716 // This is absolute index 1. Such entry does not exist.
717 &input));
718 DecodeHeaderBlock(input);
719
720 EXPECT_CALL(handler_, OnDecodingErrorDetected(
721 QUIC_QPACK_DECOMPRESSION_FAILED,
722 Eq("Dynamic table entry already evicted.")));
723
724 ASSERT_TRUE(absl::HexStringToBytes(
725 "0500" // Required Insert Count 4 and Delta Base 0.
726 // Base is 4 + 0 = 4.
727 "4200", // Literal Header Field with Name Reference instruction
728 // addressing relative index 2. This is absolute index 1. Such
729 // entry does not exist.
730 &input));
731 DecodeHeaderBlock(input);
732
733 EXPECT_CALL(handler_, OnDecodingErrorDetected(
734 QUIC_QPACK_DECOMPRESSION_FAILED,
735 Eq("Dynamic table entry already evicted.")));
736
737 ASSERT_TRUE(absl::HexStringToBytes(
738 "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
739 // Base is 2 - 0 - 1 = 1
740 "10", // Indexed Header Field instruction addressing dynamic table
741 // entry with post-base index 0, absolute index 1. Such entry
742 // does not exist.
743 &input));
744 DecodeHeaderBlock(input);
745
746 EXPECT_CALL(handler_, OnDecodingErrorDetected(
747 QUIC_QPACK_DECOMPRESSION_FAILED,
748 Eq("Dynamic table entry already evicted.")));
749
750 ASSERT_TRUE(absl::HexStringToBytes(
751 "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
752 // Base is 2 - 0 - 1 = 1
753 "0000", // Literal Header Field With Name Reference instruction
754 // addressing dynamic table entry with post-base index 0,
755 // absolute index 1. Such entry does not exist.
756 &input));
757 DecodeHeaderBlock(input);
758 }
759
TEST_P(QpackDecoderTest,TableCapacityMustNotExceedMaximum)760 TEST_P(QpackDecoderTest, TableCapacityMustNotExceedMaximum) {
761 EXPECT_CALL(
762 encoder_stream_error_delegate_,
763 OnEncoderStreamError(QUIC_QPACK_ENCODER_STREAM_SET_DYNAMIC_TABLE_CAPACITY,
764 Eq("Error updating dynamic table capacity.")));
765
766 // Try to update dynamic table capacity to 2048, which exceeds the maximum.
767 std::string input;
768 ASSERT_TRUE(absl::HexStringToBytes("3fe10f", &input));
769 DecodeEncoderStreamData(input);
770 }
771
TEST_P(QpackDecoderTest,SetDynamicTableCapacity)772 TEST_P(QpackDecoderTest, SetDynamicTableCapacity) {
773 // Update dynamic table capacity to 128, which does not exceed the maximum.
774 std::string input;
775 ASSERT_TRUE(absl::HexStringToBytes("3f61", &input));
776 DecodeEncoderStreamData(input);
777 }
778
TEST_P(QpackDecoderTest,InvalidEncodedRequiredInsertCount)779 TEST_P(QpackDecoderTest, InvalidEncodedRequiredInsertCount) {
780 // Maximum dynamic table capacity is 1024.
781 // MaxEntries is 1024 / 32 = 32.
782 // Required Insert Count is decoded modulo 2 * MaxEntries, that is, modulo 64.
783 // A value of 1 cannot be encoded as 65 even though it has the same remainder.
784 EXPECT_CALL(handler_, OnDecodingErrorDetected(
785 QUIC_QPACK_DECOMPRESSION_FAILED,
786 Eq("Error decoding Required Insert Count.")));
787 std::string input;
788 ASSERT_TRUE(absl::HexStringToBytes("4100", &input));
789 DecodeHeaderBlock(input);
790 }
791
792 // Regression test for https://crbug.com/970218: Decoder must stop processing
793 // after a Header Block Prefix with an invalid Encoded Required Insert Count.
TEST_P(QpackDecoderTest,DataAfterInvalidEncodedRequiredInsertCount)794 TEST_P(QpackDecoderTest, DataAfterInvalidEncodedRequiredInsertCount) {
795 EXPECT_CALL(handler_, OnDecodingErrorDetected(
796 QUIC_QPACK_DECOMPRESSION_FAILED,
797 Eq("Error decoding Required Insert Count.")));
798 // Header Block Prefix followed by some extra data.
799 std::string input;
800 ASSERT_TRUE(absl::HexStringToBytes("410000", &input));
801 DecodeHeaderBlock(input);
802 }
803
TEST_P(QpackDecoderTest,WrappedRequiredInsertCount)804 TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) {
805 std::string input;
806 // Maximum dynamic table capacity is 1024.
807 // MaxEntries is 1024 / 32 = 32.
808
809 // Set dynamic table capacity to 1024.
810 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
811 DecodeEncoderStreamData(input);
812 // Add literal entry with name "foo" and a 600 byte long value. This will fit
813 // in the dynamic table once but not twice.
814 ASSERT_TRUE(
815 absl::HexStringToBytes("6294e7" // Name "foo".
816 "7fd903", // Value length 600.
817 &input));
818 DecodeEncoderStreamData(input);
819
820 std::string header_value(600, 'Z');
821 DecodeEncoderStreamData(header_value);
822
823 // Duplicate most recent entry 200 times.
824 DecodeEncoderStreamData(std::string(200, '\x00'));
825
826 // Now there is only one entry in the dynamic table, with absolute index 200.
827
828 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq(header_value)));
829 EXPECT_CALL(handler_, OnDecodingCompleted());
830 EXPECT_CALL(decoder_stream_sender_delegate_,
831 WriteStreamData(Eq(kHeaderAcknowledgement)));
832
833 // Send header block with Required Insert Count = 201.
834 ASSERT_TRUE(absl::HexStringToBytes(
835 "0a00" // Encoded Required Insert Count 10, Required Insert Count 201,
836 // Delta Base 0, Base 201.
837 "80", // Emit dynamic table entry with relative index 0.
838 &input));
839 DecodeHeaderBlock(input);
840 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
841 FlushDecoderStream();
842 }
843 }
844
TEST_P(QpackDecoderTest,NonZeroRequiredInsertCountButNoDynamicEntries)845 TEST_P(QpackDecoderTest, NonZeroRequiredInsertCountButNoDynamicEntries) {
846 std::string input;
847 // Set dynamic table capacity to 1024.
848 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
849 DecodeEncoderStreamData(input);
850 // Add literal entry with name "foo" and value "bar".
851 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
852 DecodeEncoderStreamData(input);
853
854 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
855 EXPECT_CALL(handler_,
856 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
857 Eq("Required Insert Count too large.")));
858
859 ASSERT_TRUE(absl::HexStringToBytes(
860 "0200" // Required Insert Count is 1.
861 "d1", // But the only instruction references the static table.
862 &input));
863 DecodeHeaderBlock(input);
864 }
865
TEST_P(QpackDecoderTest,AddressEntryNotAllowedByRequiredInsertCount)866 TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
867 std::string input;
868 // Set dynamic table capacity to 1024.
869 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
870 DecodeEncoderStreamData(input);
871 // Add literal entry with name "foo" and value "bar".
872 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
873 DecodeEncoderStreamData(input);
874
875 EXPECT_CALL(
876 handler_,
877 OnDecodingErrorDetected(
878 QUIC_QPACK_DECOMPRESSION_FAILED,
879 Eq("Absolute Index must be smaller than Required Insert Count.")));
880
881 ASSERT_TRUE(absl::HexStringToBytes(
882 "0201" // Required Insert Count 1 and Delta Base 1.
883 // Base is 1 + 1 = 2.
884 "80", // Indexed Header Field instruction addressing dynamic table
885 // entry with relative index 0, absolute index 1. This is not
886 // allowed by Required Insert Count.
887 &input));
888 DecodeHeaderBlock(input);
889
890 EXPECT_CALL(
891 handler_,
892 OnDecodingErrorDetected(
893 QUIC_QPACK_DECOMPRESSION_FAILED,
894 Eq("Absolute Index must be smaller than Required Insert Count.")));
895
896 ASSERT_TRUE(absl::HexStringToBytes(
897 "0201" // Required Insert Count 1 and Delta Base 1.
898 // Base is 1 + 1 = 2.
899 "4000", // Literal Header Field with Name Reference instruction
900 // addressing dynamic table entry with relative index 0,
901 // absolute index 1. This is not allowed by Required Index
902 // Count.
903 &input));
904 DecodeHeaderBlock(input);
905
906 EXPECT_CALL(
907 handler_,
908 OnDecodingErrorDetected(
909 QUIC_QPACK_DECOMPRESSION_FAILED,
910 Eq("Absolute Index must be smaller than Required Insert Count.")));
911
912 ASSERT_TRUE(absl::HexStringToBytes(
913 "0200" // Required Insert Count 1 and Delta Base 0.
914 // Base is 1 + 0 = 1.
915 "10", // Indexed Header Field with Post-Base Index instruction
916 // addressing dynamic table entry with post-base index 0,
917 // absolute index 1. This is not allowed by Required Insert
918 // Count.
919 &input));
920 DecodeHeaderBlock(input);
921
922 EXPECT_CALL(
923 handler_,
924 OnDecodingErrorDetected(
925 QUIC_QPACK_DECOMPRESSION_FAILED,
926 Eq("Absolute Index must be smaller than Required Insert Count.")));
927
928 ASSERT_TRUE(absl::HexStringToBytes(
929 "0200" // Required Insert Count 1 and Delta Base 0.
930 // Base is 1 + 0 = 1.
931 "0000", // Literal Header Field with Post-Base Name Reference
932 // instruction addressing dynamic table entry with post-base
933 // index 0, absolute index 1. This is not allowed by Required
934 // Index Count.
935 &input));
936 DecodeHeaderBlock(input);
937 }
938
TEST_P(QpackDecoderTest,PromisedRequiredInsertCountLargerThanActual)939 TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
940 std::string input;
941 // Set dynamic table capacity to 1024.
942 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
943 DecodeEncoderStreamData(input);
944 // Add literal entry with name "foo" and value "bar".
945 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
946 DecodeEncoderStreamData(input);
947 // Duplicate entry twice so that decoding of header blocks with Required
948 // Insert Count not exceeding 3 is not blocked.
949 ASSERT_TRUE(absl::HexStringToBytes("00", &input));
950 DecodeEncoderStreamData(input);
951 DecodeEncoderStreamData(input);
952
953 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
954 EXPECT_CALL(handler_,
955 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
956 Eq("Required Insert Count too large.")));
957
958 ASSERT_TRUE(absl::HexStringToBytes(
959 "0300" // Required Insert Count 2 and Delta Base 0.
960 // Base is 2 + 0 = 2.
961 "81", // Indexed Header Field instruction addressing dynamic table
962 // entry with relative index 1, absolute index 0. Header block
963 // requires insert count of 1, even though Required Insert Count
964 // is 2.
965 &input));
966 DecodeHeaderBlock(input);
967
968 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
969 EXPECT_CALL(handler_,
970 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
971 Eq("Required Insert Count too large.")));
972
973 ASSERT_TRUE(absl::HexStringToBytes(
974 "0300" // Required Insert Count 2 and Delta Base 0.
975 // Base is 2 + 0 = 2.
976 "4100", // Literal Header Field with Name Reference instruction
977 // addressing dynamic table entry with relative index 1,
978 // absolute index 0. Header block requires insert count of 1,
979 // even though Required Insert Count is 2.
980 &input));
981 DecodeHeaderBlock(input);
982
983 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
984 EXPECT_CALL(handler_,
985 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
986 Eq("Required Insert Count too large.")));
987
988 ASSERT_TRUE(absl::HexStringToBytes(
989 "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
990 // Base is 3 - 1 - 1 = 1.
991 "10", // Indexed Header Field with Post-Base Index instruction
992 // addressing dynamic table entry with post-base index 0,
993 // absolute index 1. Header block requires insert count of 2,
994 // even though Required Insert Count is 3.
995 &input));
996 DecodeHeaderBlock(input);
997
998 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
999 EXPECT_CALL(handler_,
1000 OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
1001 Eq("Required Insert Count too large.")));
1002
1003 ASSERT_TRUE(absl::HexStringToBytes(
1004 "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
1005 // Base is 3 - 1 - 1 = 1.
1006 "0000", // Literal Header Field with Post-Base Name Reference
1007 // instruction addressing dynamic table entry with post-base
1008 // index 0, absolute index 1. Header block requires insert
1009 // count of 2, even though Required Insert Count is 3.
1010 &input));
1011 DecodeHeaderBlock(input);
1012 }
1013
TEST_P(QpackDecoderTest,BlockedDecoding)1014 TEST_P(QpackDecoderTest, BlockedDecoding) {
1015 std::string input;
1016 ASSERT_TRUE(absl::HexStringToBytes(
1017 "0200" // Required Insert Count 1 and Delta Base 0.
1018 // Base is 1 + 0 = 1.
1019 "80", // Indexed Header Field instruction addressing dynamic table
1020 // entry with relative index 0, absolute index 0.
1021 &input));
1022 DecodeHeaderBlock(input);
1023
1024 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
1025 EXPECT_CALL(handler_, OnDecodingCompleted());
1026 EXPECT_CALL(decoder_stream_sender_delegate_,
1027 WriteStreamData(Eq(kHeaderAcknowledgement)));
1028
1029 // Set dynamic table capacity to 1024.
1030 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
1031 DecodeEncoderStreamData(input);
1032 // Add literal entry with name "foo" and value "bar".
1033 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
1034 DecodeEncoderStreamData(input);
1035 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
1036 FlushDecoderStream();
1037 }
1038 }
1039
TEST_P(QpackDecoderTest,BlockedDecodingUnblockedBeforeEndOfHeaderBlock)1040 TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
1041 std::string input;
1042 StartDecoding();
1043 ASSERT_TRUE(absl::HexStringToBytes(
1044 "0200" // Required Insert Count 1 and Delta Base 0.
1045 // Base is 1 + 0 = 1.
1046 "80" // Indexed Header Field instruction addressing dynamic table
1047 // entry with relative index 0, absolute index 0.
1048 "d1", // Static table entry with index 17.
1049 &input));
1050 DecodeData(input);
1051
1052 // Set dynamic table capacity to 1024.
1053 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
1054 DecodeEncoderStreamData(input);
1055
1056 // Add literal entry with name "foo" and value "bar". Decoding is now
1057 // unblocked because dynamic table Insert Count reached the Required Insert
1058 // Count of the header block. |handler_| methods are called immediately for
1059 // the already consumed part of the header block.
1060 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
1061 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
1062 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
1063 DecodeEncoderStreamData(input);
1064 Mock::VerifyAndClearExpectations(&handler_);
1065
1066 // Rest of header block is processed by QpackProgressiveDecoder
1067 // in the unblocked state.
1068 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
1069 EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":scheme"), Eq("https")));
1070 ASSERT_TRUE(absl::HexStringToBytes(
1071 "80" // Indexed Header Field instruction addressing dynamic table
1072 // entry with relative index 0, absolute index 0.
1073 "d7", // Static table entry with index 23.
1074 &input));
1075 DecodeData(input);
1076 Mock::VerifyAndClearExpectations(&handler_);
1077
1078 EXPECT_CALL(handler_, OnDecodingCompleted());
1079 EXPECT_CALL(decoder_stream_sender_delegate_,
1080 WriteStreamData(Eq(kHeaderAcknowledgement)));
1081 EndDecoding();
1082 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
1083 FlushDecoderStream();
1084 }
1085 }
1086
1087 // Regression test for https://crbug.com/1024263.
TEST_P(QpackDecoderTest,BlockedDecodingUnblockedAndErrorBeforeEndOfHeaderBlock)1088 TEST_P(QpackDecoderTest,
1089 BlockedDecodingUnblockedAndErrorBeforeEndOfHeaderBlock) {
1090 std::string input;
1091 StartDecoding();
1092 ASSERT_TRUE(absl::HexStringToBytes(
1093 "0200" // Required Insert Count 1 and Delta Base 0.
1094 // Base is 1 + 0 = 1.
1095 "80" // Indexed Header Field instruction addressing dynamic table
1096 // entry with relative index 0, absolute index 0.
1097 "81", // Relative index 1 is equal to Base, therefore invalid.
1098 &input));
1099 DecodeData(input);
1100
1101 // Set dynamic table capacity to 1024.
1102 ASSERT_TRUE(absl::HexStringToBytes("3fe107", &input));
1103 DecodeEncoderStreamData(input);
1104
1105 // Add literal entry with name "foo" and value "bar". Decoding is now
1106 // unblocked because dynamic table Insert Count reached the Required Insert
1107 // Count of the header block. |handler_| methods are called immediately for
1108 // the already consumed part of the header block.
1109 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
1110 EXPECT_CALL(handler_, OnDecodingErrorDetected(QUIC_QPACK_DECOMPRESSION_FAILED,
1111 Eq("Invalid relative index.")));
1112 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
1113 DecodeEncoderStreamData(input);
1114 }
1115
1116 // Make sure that Required Insert Count is compared to Insert Count,
1117 // not size of dynamic table.
TEST_P(QpackDecoderTest,BlockedDecodingAndEvictedEntries)1118 TEST_P(QpackDecoderTest, BlockedDecodingAndEvictedEntries) {
1119 std::string input;
1120 // Update dynamic table capacity to 128.
1121 // At most three non-empty entries fit in the dynamic table.
1122 ASSERT_TRUE(absl::HexStringToBytes("3f61", &input));
1123 DecodeEncoderStreamData(input);
1124
1125 ASSERT_TRUE(absl::HexStringToBytes(
1126 "0700" // Required Insert Count 6 and Delta Base 0.
1127 // Base is 6 + 0 = 6.
1128 "80", // Indexed Header Field instruction addressing dynamic table
1129 // entry with relative index 0, absolute index 5.
1130 &input));
1131 DecodeHeaderBlock(input);
1132
1133 // Add literal entry with name "foo" and value "bar".
1134 ASSERT_TRUE(absl::HexStringToBytes("6294e703626172", &input));
1135 DecodeEncoderStreamData(input);
1136
1137 // Duplicate entry four times. This evicts the first two instances.
1138 ASSERT_TRUE(absl::HexStringToBytes("00000000", &input));
1139 DecodeEncoderStreamData(input);
1140
1141 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("baz")));
1142 EXPECT_CALL(handler_, OnDecodingCompleted());
1143 EXPECT_CALL(decoder_stream_sender_delegate_,
1144 WriteStreamData(Eq(kHeaderAcknowledgement)));
1145
1146 // Add literal entry with name "foo" and value "bar".
1147 // Insert Count is now 6, reaching Required Insert Count of the header block.
1148 ASSERT_TRUE(absl::HexStringToBytes("6294e70362617a", &input));
1149 DecodeEncoderStreamData(input);
1150 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
1151 FlushDecoderStream();
1152 }
1153 }
1154
TEST_P(QpackDecoderTest,TooManyBlockedStreams)1155 TEST_P(QpackDecoderTest, TooManyBlockedStreams) {
1156 // Required Insert Count 1 and Delta Base 0.
1157 // Without any dynamic table entries received, decoding is blocked.
1158 std::string data;
1159 ASSERT_TRUE(absl::HexStringToBytes("0200", &data));
1160
1161 auto progressive_decoder1 = CreateProgressiveDecoder(/* stream_id = */ 1);
1162 progressive_decoder1->Decode(data);
1163
1164 EXPECT_CALL(handler_,
1165 OnDecodingErrorDetected(
1166 QUIC_QPACK_DECOMPRESSION_FAILED,
1167 Eq("Limit on number of blocked streams exceeded.")));
1168
1169 auto progressive_decoder2 = CreateProgressiveDecoder(/* stream_id = */ 2);
1170 progressive_decoder2->Decode(data);
1171 }
1172
TEST_P(QpackDecoderTest,InsertCountIncrement)1173 TEST_P(QpackDecoderTest, InsertCountIncrement) {
1174 std::string input;
1175 ASSERT_TRUE(absl::HexStringToBytes(
1176 "3fe107" // Set dynamic table capacity to 1024.
1177 "6294e703626172" // Add literal entry with name "foo" and value "bar".
1178 "00", // Duplicate entry.
1179 &input));
1180 DecodeEncoderStreamData(input);
1181
1182 EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
1183 EXPECT_CALL(handler_, OnDecodingCompleted());
1184
1185 // Decoder received two insertions, but Header Acknowledgement only increases
1186 // Known Insert Count to one. Decoder should send an Insert Count Increment
1187 // instruction with increment of one to update Known Insert Count to two.
1188 std::string expected_data;
1189 ASSERT_TRUE(absl::HexStringToBytes(
1190 "81" // Header Acknowledgement on stream 1
1191 "01", // Insert Count Increment with increment of one
1192 &expected_data));
1193 EXPECT_CALL(decoder_stream_sender_delegate_,
1194 WriteStreamData(Eq(expected_data)));
1195
1196 ASSERT_TRUE(absl::HexStringToBytes(
1197 "0200" // Required Insert Count 1 and Delta Base 0.
1198 // Base is 1 + 0 = 1.
1199 "80", // Dynamic table entry with relative index 0, absolute index 0.
1200 &input));
1201 DecodeHeaderBlock(input);
1202 if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
1203 FlushDecoderStream();
1204 }
1205 }
1206
1207 } // namespace
1208 } // namespace test
1209 } // namespace quic
1210