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