• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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/spdy/core/hpack/hpack_decoder_adapter.h"
6 
7 // Tests of HpackDecoderAdapter.
8 
9 #include <stdint.h>
10 
11 #include <string>
12 #include <tuple>
13 #include <utility>
14 #include <vector>
15 
16 #include "absl/base/macros.h"
17 #include "absl/strings/escaping.h"
18 #include "quiche/http2/hpack/decoder/hpack_decoder_state.h"
19 #include "quiche/http2/hpack/decoder/hpack_decoder_tables.h"
20 #include "quiche/http2/test_tools/hpack_block_builder.h"
21 #include "quiche/http2/test_tools/http2_random.h"
22 #include "quiche/common/platform/api/quiche_logging.h"
23 #include "quiche/common/platform/api/quiche_test.h"
24 #include "quiche/common/quiche_text_utils.h"
25 #include "quiche/spdy/core/hpack/hpack_constants.h"
26 #include "quiche/spdy/core/hpack/hpack_encoder.h"
27 #include "quiche/spdy/core/hpack/hpack_output_stream.h"
28 #include "quiche/spdy/core/recording_headers_handler.h"
29 #include "quiche/spdy/test_tools/spdy_test_utils.h"
30 
31 using ::http2::HpackEntryType;
32 using ::http2::HpackStringPair;
33 using ::http2::test::HpackBlockBuilder;
34 using ::http2::test::HpackDecoderPeer;
35 using ::testing::ElementsAre;
36 using ::testing::Pair;
37 
38 namespace http2 {
39 namespace test {
40 
41 class HpackDecoderStatePeer {
42  public:
GetDecoderTables(HpackDecoderState * state)43   static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) {
44     return &state->decoder_tables_;
45   }
46 };
47 
48 class HpackDecoderPeer {
49  public:
GetDecoderState(HpackDecoder * decoder)50   static HpackDecoderState* GetDecoderState(HpackDecoder* decoder) {
51     return &decoder->decoder_state_;
52   }
GetDecoderTables(HpackDecoder * decoder)53   static HpackDecoderTables* GetDecoderTables(HpackDecoder* decoder) {
54     return HpackDecoderStatePeer::GetDecoderTables(GetDecoderState(decoder));
55   }
56 };
57 
58 }  // namespace test
59 }  // namespace http2
60 
61 namespace spdy {
62 namespace test {
63 
64 class HpackDecoderAdapterPeer {
65  public:
HpackDecoderAdapterPeer(HpackDecoderAdapter * decoder)66   explicit HpackDecoderAdapterPeer(HpackDecoderAdapter* decoder)
67       : decoder_(decoder) {}
68 
HandleHeaderRepresentation(const std::string & name,const std::string & value)69   void HandleHeaderRepresentation(const std::string& name,
70                                   const std::string& value) {
71     decoder_->listener_adapter_.OnHeader(name, value);
72   }
73 
GetDecoderTables()74   http2::HpackDecoderTables* GetDecoderTables() {
75     return HpackDecoderPeer::GetDecoderTables(&decoder_->hpack_decoder_);
76   }
77 
GetTableEntry(uint32_t index)78   const HpackStringPair* GetTableEntry(uint32_t index) {
79     return GetDecoderTables()->Lookup(index);
80   }
81 
current_header_table_size()82   size_t current_header_table_size() {
83     return GetDecoderTables()->current_header_table_size();
84   }
85 
header_table_size_limit()86   size_t header_table_size_limit() {
87     return GetDecoderTables()->header_table_size_limit();
88   }
89 
set_header_table_size_limit(size_t size)90   void set_header_table_size_limit(size_t size) {
91     return GetDecoderTables()->DynamicTableSizeUpdate(size);
92   }
93 
94  private:
95   HpackDecoderAdapter* decoder_;
96 };
97 
98 class HpackEncoderPeer {
99  public:
CookieToCrumbs(const HpackEncoder::Representation & cookie,HpackEncoder::Representations * crumbs_out)100   static void CookieToCrumbs(const HpackEncoder::Representation& cookie,
101                              HpackEncoder::Representations* crumbs_out) {
102     HpackEncoder::CookieToCrumbs(cookie, crumbs_out);
103   }
104 };
105 
106 namespace {
107 
108 const bool kNoCheckDecodedSize = false;
109 const char* kCookieKey = "cookie";
110 
111 // Is HandleControlFrameHeadersStart to be called, and with what value?
112 enum StartChoice { START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START };
113 
114 class HpackDecoderAdapterTest
115     : public quiche::test::QuicheTestWithParam<std::tuple<StartChoice, bool>> {
116  protected:
HpackDecoderAdapterTest()117   HpackDecoderAdapterTest() : decoder_(), decoder_peer_(&decoder_) {}
118 
SetUp()119   void SetUp() override {
120     std::tie(start_choice_, randomly_split_input_buffer_) = GetParam();
121   }
122 
HandleControlFrameHeadersStart()123   void HandleControlFrameHeadersStart() {
124     bytes_passed_in_ = 0;
125     switch (start_choice_) {
126       case START_WITH_HANDLER:
127         decoder_.HandleControlFrameHeadersStart(&handler_);
128         break;
129       case START_WITHOUT_HANDLER:
130         decoder_.HandleControlFrameHeadersStart(nullptr);
131         break;
132       case NO_START:
133         break;
134     }
135   }
136 
HandleControlFrameHeadersData(absl::string_view str)137   bool HandleControlFrameHeadersData(absl::string_view str) {
138     QUICHE_VLOG(3) << "HandleControlFrameHeadersData:\n"
139                    << quiche::QuicheTextUtils::HexDump(str);
140     bytes_passed_in_ += str.size();
141     return decoder_.HandleControlFrameHeadersData(str.data(), str.size());
142   }
143 
HandleControlFrameHeadersComplete()144   bool HandleControlFrameHeadersComplete() {
145     bool rc = decoder_.HandleControlFrameHeadersComplete();
146     return rc;
147   }
148 
DecodeHeaderBlock(absl::string_view str,bool check_decoded_size=true)149   bool DecodeHeaderBlock(absl::string_view str,
150                          bool check_decoded_size = true) {
151     // Don't call this again if HandleControlFrameHeadersData failed previously.
152     EXPECT_FALSE(decode_has_failed_);
153     HandleControlFrameHeadersStart();
154     if (randomly_split_input_buffer_) {
155       do {
156         // Decode some fragment of the remaining bytes.
157         size_t bytes = str.size();
158         if (!str.empty()) {
159           bytes = random_.Uniform(str.size()) + 1;
160         }
161         EXPECT_LE(bytes, str.size());
162         if (!HandleControlFrameHeadersData(str.substr(0, bytes))) {
163           decode_has_failed_ = true;
164           return false;
165         }
166         str.remove_prefix(bytes);
167       } while (!str.empty());
168     } else if (!HandleControlFrameHeadersData(str)) {
169       decode_has_failed_ = true;
170       return false;
171     }
172     if (start_choice_ == START_WITH_HANDLER) {
173       if (!HandleControlFrameHeadersComplete()) {
174         decode_has_failed_ = true;
175         return false;
176       }
177       EXPECT_EQ(handler_.compressed_header_bytes(), bytes_passed_in_);
178     } else {
179       if (!HandleControlFrameHeadersComplete()) {
180         decode_has_failed_ = true;
181         return false;
182       }
183     }
184     if (check_decoded_size && start_choice_ == START_WITH_HANDLER) {
185       EXPECT_EQ(handler_.uncompressed_header_bytes(),
186                 SizeOfHeaders(decoded_block()));
187     }
188     return true;
189   }
190 
EncodeAndDecodeDynamicTableSizeUpdates(size_t first,size_t second)191   bool EncodeAndDecodeDynamicTableSizeUpdates(size_t first, size_t second) {
192     HpackBlockBuilder hbb;
193     hbb.AppendDynamicTableSizeUpdate(first);
194     if (second != first) {
195       hbb.AppendDynamicTableSizeUpdate(second);
196     }
197     return DecodeHeaderBlock(hbb.buffer());
198   }
199 
decoded_block() const200   const Http2HeaderBlock& decoded_block() const {
201     if (start_choice_ == START_WITH_HANDLER) {
202       return handler_.decoded_block();
203     } else {
204       return decoder_.decoded_block();
205     }
206   }
207 
SizeOfHeaders(const Http2HeaderBlock & headers)208   static size_t SizeOfHeaders(const Http2HeaderBlock& headers) {
209     size_t size = 0;
210     for (const auto& kv : headers) {
211       if (kv.first == kCookieKey) {
212         HpackEncoder::Representations crumbs;
213         HpackEncoderPeer::CookieToCrumbs(kv, &crumbs);
214         for (const auto& crumb : crumbs) {
215           size += crumb.first.size() + crumb.second.size();
216         }
217       } else {
218         size += kv.first.size() + kv.second.size();
219       }
220     }
221     return size;
222   }
223 
DecodeBlockExpectingSuccess(absl::string_view str)224   const Http2HeaderBlock& DecodeBlockExpectingSuccess(absl::string_view str) {
225     EXPECT_TRUE(DecodeHeaderBlock(str));
226     return decoded_block();
227   }
228 
expectEntry(size_t index,size_t size,const std::string & name,const std::string & value)229   void expectEntry(size_t index, size_t size, const std::string& name,
230                    const std::string& value) {
231     const HpackStringPair* entry = decoder_peer_.GetTableEntry(index);
232     EXPECT_EQ(name, entry->name) << "index " << index;
233     EXPECT_EQ(value, entry->value);
234     EXPECT_EQ(size, entry->size());
235   }
236 
MakeHeaderBlock(const std::vector<std::pair<std::string,std::string>> & headers)237   Http2HeaderBlock MakeHeaderBlock(
238       const std::vector<std::pair<std::string, std::string>>& headers) {
239     Http2HeaderBlock result;
240     for (const auto& kv : headers) {
241       result.AppendValueOrAddHeader(kv.first, kv.second);
242     }
243     return result;
244   }
245 
246   http2::test::Http2Random random_;
247   HpackDecoderAdapter decoder_;
248   test::HpackDecoderAdapterPeer decoder_peer_;
249   RecordingHeadersHandler handler_;
250   StartChoice start_choice_;
251   bool randomly_split_input_buffer_;
252   bool decode_has_failed_ = false;
253   size_t bytes_passed_in_;
254 };
255 
256 INSTANTIATE_TEST_SUITE_P(
257     NoHandler, HpackDecoderAdapterTest,
258     ::testing::Combine(::testing::Values(START_WITHOUT_HANDLER, NO_START),
259                        ::testing::Bool()));
260 
261 INSTANTIATE_TEST_SUITE_P(
262     WithHandler, HpackDecoderAdapterTest,
263     ::testing::Combine(::testing::Values(START_WITH_HANDLER),
264                        ::testing::Bool()));
265 
TEST_P(HpackDecoderAdapterTest,ApplyHeaderTableSizeSetting)266 TEST_P(HpackDecoderAdapterTest, ApplyHeaderTableSizeSetting) {
267   EXPECT_EQ(4096u, decoder_.GetCurrentHeaderTableSizeSetting());
268   decoder_.ApplyHeaderTableSizeSetting(12 * 1024);
269   EXPECT_EQ(12288u, decoder_.GetCurrentHeaderTableSizeSetting());
270 }
271 
TEST_P(HpackDecoderAdapterTest,AddHeaderDataWithHandleControlFrameHeadersData)272 TEST_P(HpackDecoderAdapterTest,
273        AddHeaderDataWithHandleControlFrameHeadersData) {
274   // The hpack decode buffer size is limited in size. This test verifies that
275   // adding encoded data under that limit is accepted, and data that exceeds the
276   // limit is rejected.
277   HandleControlFrameHeadersStart();
278   const size_t kMaxBufferSizeBytes = 50;
279   const std::string a_value = std::string(49, 'x');
280   decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
281   HpackBlockBuilder hbb;
282   hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
283                                 false, "a", false, a_value);
284   const std::string& s = hbb.buffer();
285   EXPECT_GT(s.size(), kMaxBufferSizeBytes);
286 
287   // Any one in input buffer must not exceed kMaxBufferSizeBytes.
288   EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(0, s.size() / 2)));
289   EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(s.size() / 2)));
290 
291   EXPECT_FALSE(HandleControlFrameHeadersData(s));
292   Http2HeaderBlock expected_block = MakeHeaderBlock({{"a", a_value}});
293   EXPECT_EQ(expected_block, decoded_block());
294 }
295 
TEST_P(HpackDecoderAdapterTest,NameTooLong)296 TEST_P(HpackDecoderAdapterTest, NameTooLong) {
297   // Verify that a name longer than the allowed size generates an error.
298   const size_t kMaxBufferSizeBytes = 50;
299   const std::string name = std::string(2 * kMaxBufferSizeBytes, 'x');
300   const std::string value = "abc";
301 
302   decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
303 
304   HpackBlockBuilder hbb;
305   hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
306                                 false, name, false, value);
307 
308   const size_t fragment_size = (3 * kMaxBufferSizeBytes) / 2;
309   const std::string fragment = hbb.buffer().substr(0, fragment_size);
310 
311   HandleControlFrameHeadersStart();
312   EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
313 }
314 
TEST_P(HpackDecoderAdapterTest,HeaderTooLongToBuffer)315 TEST_P(HpackDecoderAdapterTest, HeaderTooLongToBuffer) {
316   // Verify that a header longer than the allowed size generates an error if
317   // it isn't all in one input buffer.
318   const std::string name = "some-key";
319   const std::string value = "some-value";
320   const size_t kMaxBufferSizeBytes = name.size() + value.size() - 2;
321   decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
322 
323   HpackBlockBuilder hbb;
324   hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
325                                 false, name, false, value);
326   const size_t fragment_size = hbb.size() - 1;
327   const std::string fragment = hbb.buffer().substr(0, fragment_size);
328 
329   HandleControlFrameHeadersStart();
330   EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
331 }
332 
333 // Verify that a header block that exceeds the maximum length is rejected.
TEST_P(HpackDecoderAdapterTest,HeaderBlockTooLong)334 TEST_P(HpackDecoderAdapterTest, HeaderBlockTooLong) {
335   const std::string name = "some-key";
336   const std::string value = "some-value";
337   const size_t kMaxBufferSizeBytes = 1024;
338 
339   HpackBlockBuilder hbb;
340   hbb.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, false,
341                                 name, false, value);
342   while (hbb.size() < kMaxBufferSizeBytes) {
343     hbb.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, false,
344                                   "", false, "");
345   }
346   // With no limit on the maximum header block size, the decoder handles the
347   // entire block successfully.
348   HandleControlFrameHeadersStart();
349   EXPECT_TRUE(HandleControlFrameHeadersData(hbb.buffer()));
350   EXPECT_TRUE(HandleControlFrameHeadersComplete());
351 
352   // When a total byte limit is imposed, the decoder bails before the end of the
353   // block.
354   decoder_.set_max_header_block_bytes(kMaxBufferSizeBytes);
355   HandleControlFrameHeadersStart();
356   EXPECT_FALSE(HandleControlFrameHeadersData(hbb.buffer()));
357 }
358 
359 // Decode with incomplete data in buffer.
TEST_P(HpackDecoderAdapterTest,DecodeWithIncompleteData)360 TEST_P(HpackDecoderAdapterTest, DecodeWithIncompleteData) {
361   HandleControlFrameHeadersStart();
362 
363   // No need to wait for more data.
364   EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82"));
365   std::vector<std::pair<std::string, std::string>> expected_headers = {
366       {":method", "GET"}, {":path", "/index.html"}, {":method", "GET"}};
367 
368   Http2HeaderBlock expected_block1 = MakeHeaderBlock(expected_headers);
369   EXPECT_EQ(expected_block1, decoded_block());
370 
371   // Full and partial headers, won't add partial to the headers.
372   EXPECT_TRUE(
373       HandleControlFrameHeadersData("\x40\x03goo"
374                                     "\x03gar\xbe\x40\x04spam"));
375   expected_headers.push_back({"goo", "gar"});
376   expected_headers.push_back({"goo", "gar"});
377 
378   Http2HeaderBlock expected_block2 = MakeHeaderBlock(expected_headers);
379   EXPECT_EQ(expected_block2, decoded_block());
380 
381   // Add the needed data.
382   EXPECT_TRUE(HandleControlFrameHeadersData("\x04gggs"));
383 
384   EXPECT_TRUE(HandleControlFrameHeadersComplete());
385 
386   expected_headers.push_back({"spam", "gggs"});
387 
388   Http2HeaderBlock expected_block3 = MakeHeaderBlock(expected_headers);
389   EXPECT_EQ(expected_block3, decoded_block());
390 }
391 
TEST_P(HpackDecoderAdapterTest,HandleHeaderRepresentation)392 TEST_P(HpackDecoderAdapterTest, HandleHeaderRepresentation) {
393   // Make sure the decoder is properly initialized.
394   HandleControlFrameHeadersStart();
395   HandleControlFrameHeadersData("");
396 
397   // All cookie crumbs are joined.
398   decoder_peer_.HandleHeaderRepresentation("cookie", " part 1");
399   decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 ");
400   decoder_peer_.HandleHeaderRepresentation("cookie", "part3");
401 
402   // Already-delimited headers are passed through.
403   decoder_peer_.HandleHeaderRepresentation("passed-through",
404                                            std::string("foo\0baz", 7));
405 
406   // Other headers are joined on \0. Case matters.
407   decoder_peer_.HandleHeaderRepresentation("joined", "joined");
408   decoder_peer_.HandleHeaderRepresentation("joineD", "value 1");
409   decoder_peer_.HandleHeaderRepresentation("joineD", "value 2");
410 
411   // Empty headers remain empty.
412   decoder_peer_.HandleHeaderRepresentation("empty", "");
413 
414   // Joined empty headers work as expected.
415   decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
416   decoder_peer_.HandleHeaderRepresentation("empty-joined", "foo");
417   decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
418   decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
419 
420   // Non-contiguous cookie crumb.
421   decoder_peer_.HandleHeaderRepresentation("cookie", " fin!");
422 
423   // Finish and emit all headers.
424   decoder_.HandleControlFrameHeadersComplete();
425 
426   // Resulting decoded headers are in the same order as the inputs.
427   EXPECT_THAT(
428       decoded_block(),
429       ElementsAre(
430           Pair("cookie", " part 1; part 2 ; part3;  fin!"),
431           Pair("passed-through", absl::string_view("foo\0baz", 7)),
432           Pair("joined", absl::string_view("joined\0value 1\0value 2", 22)),
433           Pair("empty", ""),
434           Pair("empty-joined", absl::string_view("\0foo\0\0", 6))));
435 }
436 
437 // Decoding indexed static table field should work.
TEST_P(HpackDecoderAdapterTest,IndexedHeaderStatic)438 TEST_P(HpackDecoderAdapterTest, IndexedHeaderStatic) {
439   // Reference static table entries #2 and #5.
440   const Http2HeaderBlock& header_set1 = DecodeBlockExpectingSuccess("\x82\x85");
441   Http2HeaderBlock expected_header_set1;
442   expected_header_set1[":method"] = "GET";
443   expected_header_set1[":path"] = "/index.html";
444   EXPECT_EQ(expected_header_set1, header_set1);
445 
446   // Reference static table entry #2.
447   const Http2HeaderBlock& header_set2 = DecodeBlockExpectingSuccess("\x82");
448   Http2HeaderBlock expected_header_set2;
449   expected_header_set2[":method"] = "GET";
450   EXPECT_EQ(expected_header_set2, header_set2);
451 }
452 
TEST_P(HpackDecoderAdapterTest,IndexedHeaderDynamic)453 TEST_P(HpackDecoderAdapterTest, IndexedHeaderDynamic) {
454   // First header block: add an entry to header table.
455   const Http2HeaderBlock& header_set1 = DecodeBlockExpectingSuccess(
456       "\x40\x03"
457       "foo"
458       "\x03"
459       "bar");
460   Http2HeaderBlock expected_header_set1;
461   expected_header_set1["foo"] = "bar";
462   EXPECT_EQ(expected_header_set1, header_set1);
463 
464   // Second header block: add another entry to header table.
465   const Http2HeaderBlock& header_set2 = DecodeBlockExpectingSuccess(
466       "\xbe\x40\x04"
467       "spam"
468       "\x04"
469       "eggs");
470   Http2HeaderBlock expected_header_set2;
471   expected_header_set2["foo"] = "bar";
472   expected_header_set2["spam"] = "eggs";
473   EXPECT_EQ(expected_header_set2, header_set2);
474 
475   // Third header block: refer to most recently added entry.
476   const Http2HeaderBlock& header_set3 = DecodeBlockExpectingSuccess("\xbe");
477   Http2HeaderBlock expected_header_set3;
478   expected_header_set3["spam"] = "eggs";
479   EXPECT_EQ(expected_header_set3, header_set3);
480 }
481 
482 // Test a too-large indexed header.
TEST_P(HpackDecoderAdapterTest,InvalidIndexedHeader)483 TEST_P(HpackDecoderAdapterTest, InvalidIndexedHeader) {
484   // High-bit set, and a prefix of one more than the number of static entries.
485   EXPECT_FALSE(DecodeHeaderBlock("\xbe"));
486 }
487 
TEST_P(HpackDecoderAdapterTest,ContextUpdateMaximumSize)488 TEST_P(HpackDecoderAdapterTest, ContextUpdateMaximumSize) {
489   EXPECT_EQ(kDefaultHeaderTableSizeSetting,
490             decoder_peer_.header_table_size_limit());
491   std::string input;
492   {
493     // Maximum-size update with size 126. Succeeds.
494     HpackOutputStream output_stream;
495     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
496     output_stream.AppendUint32(126);
497 
498     input = output_stream.TakeString();
499     EXPECT_TRUE(DecodeHeaderBlock(input));
500     EXPECT_EQ(126u, decoder_peer_.header_table_size_limit());
501   }
502   {
503     // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds.
504     HpackOutputStream output_stream;
505     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
506     output_stream.AppendUint32(kDefaultHeaderTableSizeSetting);
507 
508     input = output_stream.TakeString();
509     EXPECT_TRUE(DecodeHeaderBlock(input));
510     EXPECT_EQ(kDefaultHeaderTableSizeSetting,
511               decoder_peer_.header_table_size_limit());
512   }
513   {
514     // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails.
515     HpackOutputStream output_stream;
516     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
517     output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1);
518 
519     input = output_stream.TakeString();
520     EXPECT_FALSE(DecodeHeaderBlock(input));
521     EXPECT_EQ(kDefaultHeaderTableSizeSetting,
522               decoder_peer_.header_table_size_limit());
523   }
524 }
525 
526 // Two HeaderTableSizeUpdates may appear at the beginning of the block
TEST_P(HpackDecoderAdapterTest,TwoTableSizeUpdates)527 TEST_P(HpackDecoderAdapterTest, TwoTableSizeUpdates) {
528   std::string input;
529   {
530     // Should accept two table size updates, update to second one
531     HpackOutputStream output_stream;
532     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
533     output_stream.AppendUint32(0);
534     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
535     output_stream.AppendUint32(122);
536 
537     input = output_stream.TakeString();
538     EXPECT_TRUE(DecodeHeaderBlock(input));
539     EXPECT_EQ(122u, decoder_peer_.header_table_size_limit());
540   }
541 }
542 
543 // Three HeaderTableSizeUpdates should result in an error
TEST_P(HpackDecoderAdapterTest,ThreeTableSizeUpdatesError)544 TEST_P(HpackDecoderAdapterTest, ThreeTableSizeUpdatesError) {
545   std::string input;
546   {
547     // Should reject three table size updates, update to second one
548     HpackOutputStream output_stream;
549     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
550     output_stream.AppendUint32(5);
551     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
552     output_stream.AppendUint32(10);
553     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
554     output_stream.AppendUint32(15);
555 
556     input = output_stream.TakeString();
557 
558     EXPECT_FALSE(DecodeHeaderBlock(input));
559     EXPECT_EQ(10u, decoder_peer_.header_table_size_limit());
560   }
561 }
562 
563 // HeaderTableSizeUpdates may only appear at the beginning of the block
564 // Any other updates should result in an error
TEST_P(HpackDecoderAdapterTest,TableSizeUpdateSecondError)565 TEST_P(HpackDecoderAdapterTest, TableSizeUpdateSecondError) {
566   std::string input;
567   {
568     // Should reject a table size update appearing after a different entry
569     // The table size should remain as the default
570     HpackOutputStream output_stream;
571     output_stream.AppendBytes("\x82\x85");
572     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
573     output_stream.AppendUint32(123);
574 
575     input = output_stream.TakeString();
576 
577     EXPECT_FALSE(DecodeHeaderBlock(input));
578     EXPECT_EQ(kDefaultHeaderTableSizeSetting,
579               decoder_peer_.header_table_size_limit());
580   }
581 }
582 
583 // HeaderTableSizeUpdates may only appear at the beginning of the block
584 // Any other updates should result in an error
TEST_P(HpackDecoderAdapterTest,TableSizeUpdateFirstThirdError)585 TEST_P(HpackDecoderAdapterTest, TableSizeUpdateFirstThirdError) {
586   std::string input;
587   {
588     // Should reject the second table size update
589     // if a different entry appears after the first update
590     // The table size should update to the first but not the second
591     HpackOutputStream output_stream;
592     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
593     output_stream.AppendUint32(60);
594     output_stream.AppendBytes("\x82\x85");
595     output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
596     output_stream.AppendUint32(125);
597 
598     input = output_stream.TakeString();
599 
600     EXPECT_FALSE(DecodeHeaderBlock(input));
601     EXPECT_EQ(60u, decoder_peer_.header_table_size_limit());
602   }
603 }
604 
605 // Decoding two valid encoded literal headers with no indexing should
606 // work.
TEST_P(HpackDecoderAdapterTest,LiteralHeaderNoIndexing)607 TEST_P(HpackDecoderAdapterTest, LiteralHeaderNoIndexing) {
608   // First header with indexed name, second header with string literal
609   // name.
610   const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2";
611   const Http2HeaderBlock& header_set = DecodeBlockExpectingSuccess(
612       absl::string_view(input, ABSL_ARRAYSIZE(input) - 1));
613 
614   Http2HeaderBlock expected_header_set;
615   expected_header_set[":path"] = "/sample/path";
616   expected_header_set[":path2"] = "/sample/path/2";
617   EXPECT_EQ(expected_header_set, header_set);
618 }
619 
620 // Decoding two valid encoded literal headers with incremental
621 // indexing and string literal names should work.
TEST_P(HpackDecoderAdapterTest,LiteralHeaderIncrementalIndexing)622 TEST_P(HpackDecoderAdapterTest, LiteralHeaderIncrementalIndexing) {
623   const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2";
624   const Http2HeaderBlock& header_set = DecodeBlockExpectingSuccess(
625       absl::string_view(input, ABSL_ARRAYSIZE(input) - 1));
626 
627   Http2HeaderBlock expected_header_set;
628   expected_header_set[":path"] = "/sample/path";
629   expected_header_set[":path2"] = "/sample/path/2";
630   EXPECT_EQ(expected_header_set, header_set);
631 }
632 
TEST_P(HpackDecoderAdapterTest,LiteralHeaderWithIndexingInvalidNameIndex)633 TEST_P(HpackDecoderAdapterTest, LiteralHeaderWithIndexingInvalidNameIndex) {
634   decoder_.ApplyHeaderTableSizeSetting(0);
635   EXPECT_TRUE(EncodeAndDecodeDynamicTableSizeUpdates(0, 0));
636 
637   // Name is the last static index. Works.
638   EXPECT_TRUE(DecodeHeaderBlock(absl::string_view("\x7d\x03ooo")));
639   // Name is one beyond the last static index. Fails.
640   EXPECT_FALSE(DecodeHeaderBlock(absl::string_view("\x7e\x03ooo")));
641 }
642 
TEST_P(HpackDecoderAdapterTest,LiteralHeaderNoIndexingInvalidNameIndex)643 TEST_P(HpackDecoderAdapterTest, LiteralHeaderNoIndexingInvalidNameIndex) {
644   // Name is the last static index. Works.
645   EXPECT_TRUE(DecodeHeaderBlock(absl::string_view("\x0f\x2e\x03ooo")));
646   // Name is one beyond the last static index. Fails.
647   EXPECT_FALSE(DecodeHeaderBlock(absl::string_view("\x0f\x2f\x03ooo")));
648 }
649 
TEST_P(HpackDecoderAdapterTest,LiteralHeaderNeverIndexedInvalidNameIndex)650 TEST_P(HpackDecoderAdapterTest, LiteralHeaderNeverIndexedInvalidNameIndex) {
651   // Name is the last static index. Works.
652   EXPECT_TRUE(DecodeHeaderBlock(absl::string_view("\x1f\x2e\x03ooo")));
653   // Name is one beyond the last static index. Fails.
654   EXPECT_FALSE(DecodeHeaderBlock(absl::string_view("\x1f\x2f\x03ooo")));
655 }
656 
TEST_P(HpackDecoderAdapterTest,TruncatedIndex)657 TEST_P(HpackDecoderAdapterTest, TruncatedIndex) {
658   // Indexed Header, varint for index requires multiple bytes,
659   // but only one provided.
660   EXPECT_FALSE(DecodeHeaderBlock("\xff"));
661 }
662 
TEST_P(HpackDecoderAdapterTest,TruncatedHuffmanLiteral)663 TEST_P(HpackDecoderAdapterTest, TruncatedHuffmanLiteral) {
664   // Literal value, Huffman encoded, but with the last byte missing (i.e.
665   // drop the final ff shown below).
666   //
667   // 41                                      | == Literal indexed ==
668   //                                         |   Indexed name (idx = 1)
669   //                                         |     :authority
670   // 8c                                      |   Literal value (len = 12)
671   //                                         |     Huffman encoded:
672   // f1e3 c2e5 f23a 6ba0 ab90 f4ff           | .....:k.....
673   //                                         |     Decoded:
674   //                                         | www.example.com
675   //                                         | -> :authority: www.example.com
676 
677   std::string first = absl::HexStringToBytes("418cf1e3c2e5f23a6ba0ab90f4ff");
678   EXPECT_TRUE(DecodeHeaderBlock(first));
679   first.pop_back();
680   EXPECT_FALSE(DecodeHeaderBlock(first));
681 }
682 
TEST_P(HpackDecoderAdapterTest,HuffmanEOSError)683 TEST_P(HpackDecoderAdapterTest, HuffmanEOSError) {
684   // Literal value, Huffman encoded, but with an additional ff byte at the end
685   // of the string, i.e. an EOS that is longer than permitted.
686   //
687   // 41                                      | == Literal indexed ==
688   //                                         |   Indexed name (idx = 1)
689   //                                         |     :authority
690   // 8d                                      |   Literal value (len = 13)
691   //                                         |     Huffman encoded:
692   // f1e3 c2e5 f23a 6ba0 ab90 f4ff           | .....:k.....
693   //                                         |     Decoded:
694   //                                         | www.example.com
695   //                                         | -> :authority: www.example.com
696 
697   std::string first = absl::HexStringToBytes("418cf1e3c2e5f23a6ba0ab90f4ff");
698   EXPECT_TRUE(DecodeHeaderBlock(first));
699   first = absl::HexStringToBytes("418df1e3c2e5f23a6ba0ab90f4ffff");
700   EXPECT_FALSE(DecodeHeaderBlock(first));
701 }
702 
703 // Round-tripping the header set from RFC 7541 C.3.1 should work.
704 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
TEST_P(HpackDecoderAdapterTest,BasicC31)705 TEST_P(HpackDecoderAdapterTest, BasicC31) {
706   HpackEncoder encoder;
707 
708   Http2HeaderBlock expected_header_set;
709   expected_header_set[":method"] = "GET";
710   expected_header_set[":scheme"] = "http";
711   expected_header_set[":path"] = "/";
712   expected_header_set[":authority"] = "www.example.com";
713 
714   std::string encoded_header_set =
715       encoder.EncodeHeaderBlock(expected_header_set);
716 
717   EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set));
718   EXPECT_EQ(expected_header_set, decoded_block());
719 }
720 
721 // RFC 7541, Section C.4: Request Examples with Huffman Coding
722 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.4
TEST_P(HpackDecoderAdapterTest,SectionC4RequestHuffmanExamples)723 TEST_P(HpackDecoderAdapterTest, SectionC4RequestHuffmanExamples) {
724   // TODO(jamessynge): Use http2/hpack/tools/hpack_example.h to parse the
725   // example directly, instead of having it as a comment.
726   //
727   // 82                                      | == Indexed - Add ==
728   //                                         |   idx = 2
729   //                                         | -> :method: GET
730   // 86                                      | == Indexed - Add ==
731   //                                         |   idx = 6
732   //                                         | -> :scheme: http
733   // 84                                      | == Indexed - Add ==
734   //                                         |   idx = 4
735   //                                         | -> :path: /
736   // 41                                      | == Literal indexed ==
737   //                                         |   Indexed name (idx = 1)
738   //                                         |     :authority
739   // 8c                                      |   Literal value (len = 12)
740   //                                         |     Huffman encoded:
741   // f1e3 c2e5 f23a 6ba0 ab90 f4ff           | .....:k.....
742   //                                         |     Decoded:
743   //                                         | www.example.com
744   //                                         | -> :authority: www.example.com
745   std::string first =
746       absl::HexStringToBytes("828684418cf1e3c2e5f23a6ba0ab90f4ff");
747   const Http2HeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
748 
749   EXPECT_THAT(first_header_set,
750               ElementsAre(
751                   // clang-format off
752       Pair(":method", "GET"),
753       Pair(":scheme", "http"),
754       Pair(":path", "/"),
755       Pair(":authority", "www.example.com")));
756   // clang-format on
757 
758   expectEntry(62, 57, ":authority", "www.example.com");
759   EXPECT_EQ(57u, decoder_peer_.current_header_table_size());
760 
761   // 82                                      | == Indexed - Add ==
762   //                                         |   idx = 2
763   //                                         | -> :method: GET
764   // 86                                      | == Indexed - Add ==
765   //                                         |   idx = 6
766   //                                         | -> :scheme: http
767   // 84                                      | == Indexed - Add ==
768   //                                         |   idx = 4
769   //                                         | -> :path: /
770   // be                                      | == Indexed - Add ==
771   //                                         |   idx = 62
772   //                                         | -> :authority: www.example.com
773   // 58                                      | == Literal indexed ==
774   //                                         |   Indexed name (idx = 24)
775   //                                         |     cache-control
776   // 86                                      |   Literal value (len = 8)
777   //                                         |     Huffman encoded:
778   // a8eb 1064 9cbf                          | ...d..
779   //                                         |     Decoded:
780   //                                         | no-cache
781   //                                         | -> cache-control: no-cache
782 
783   std::string second = absl::HexStringToBytes("828684be5886a8eb10649cbf");
784   const Http2HeaderBlock& second_header_set =
785       DecodeBlockExpectingSuccess(second);
786 
787   EXPECT_THAT(second_header_set,
788               ElementsAre(
789                   // clang-format off
790       Pair(":method", "GET"),
791       Pair(":scheme", "http"),
792       Pair(":path", "/"),
793       Pair(":authority", "www.example.com"),
794       Pair("cache-control", "no-cache")));
795   // clang-format on
796 
797   expectEntry(62, 53, "cache-control", "no-cache");
798   expectEntry(63, 57, ":authority", "www.example.com");
799   EXPECT_EQ(110u, decoder_peer_.current_header_table_size());
800 
801   // 82                                      | == Indexed - Add ==
802   //                                         |   idx = 2
803   //                                         | -> :method: GET
804   // 87                                      | == Indexed - Add ==
805   //                                         |   idx = 7
806   //                                         | -> :scheme: https
807   // 85                                      | == Indexed - Add ==
808   //                                         |   idx = 5
809   //                                         | -> :path: /index.html
810   // bf                                      | == Indexed - Add ==
811   //                                         |   idx = 63
812   //                                         | -> :authority: www.example.com
813   // 40                                      | == Literal indexed ==
814   // 88                                      |   Literal name (len = 10)
815   //                                         |     Huffman encoded:
816   // 25a8 49e9 5ba9 7d7f                     | %.I.[.}.
817   //                                         |     Decoded:
818   //                                         | custom-key
819   // 89                                      |   Literal value (len = 12)
820   //                                         |     Huffman encoded:
821   // 25a8 49e9 5bb8 e8b4 bf                  | %.I.[....
822   //                                         |     Decoded:
823   //                                         | custom-value
824   //                                         | -> custom-key: custom-value
825   std::string third = absl::HexStringToBytes(
826       "828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf");
827   const Http2HeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
828 
829   EXPECT_THAT(
830       third_header_set,
831       ElementsAre(
832           // clang-format off
833       Pair(":method", "GET"),
834       Pair(":scheme", "https"),
835       Pair(":path", "/index.html"),
836       Pair(":authority", "www.example.com"),
837       Pair("custom-key", "custom-value")));
838   // clang-format on
839 
840   expectEntry(62, 54, "custom-key", "custom-value");
841   expectEntry(63, 53, "cache-control", "no-cache");
842   expectEntry(64, 57, ":authority", "www.example.com");
843   EXPECT_EQ(164u, decoder_peer_.current_header_table_size());
844 }
845 
846 // RFC 7541, Section C.6: Response Examples with Huffman Coding
847 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.6
TEST_P(HpackDecoderAdapterTest,SectionC6ResponseHuffmanExamples)848 TEST_P(HpackDecoderAdapterTest, SectionC6ResponseHuffmanExamples) {
849   // The example is based on a maximum dynamic table size of 256,
850   // which allows for testing dynamic table evictions.
851   decoder_peer_.set_header_table_size_limit(256);
852 
853   // 48                                      | == Literal indexed ==
854   //                                         |   Indexed name (idx = 8)
855   //                                         |     :status
856   // 82                                      |   Literal value (len = 3)
857   //                                         |     Huffman encoded:
858   // 6402                                    | d.
859   //                                         |     Decoded:
860   //                                         | 302
861   //                                         | -> :status: 302
862   // 58                                      | == Literal indexed ==
863   //                                         |   Indexed name (idx = 24)
864   //                                         |     cache-control
865   // 85                                      |   Literal value (len = 7)
866   //                                         |     Huffman encoded:
867   // aec3 771a 4b                            | ..w.K
868   //                                         |     Decoded:
869   //                                         | private
870   //                                         | -> cache-control: private
871   // 61                                      | == Literal indexed ==
872   //                                         |   Indexed name (idx = 33)
873   //                                         |     date
874   // 96                                      |   Literal value (len = 29)
875   //                                         |     Huffman encoded:
876   // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
877   // e082 a62d 1bff                          | ...-..
878   //                                         |     Decoded:
879   //                                         | Mon, 21 Oct 2013 20:13:21
880   //                                         | GMT
881   //                                         | -> date: Mon, 21 Oct 2013
882   //                                         |   20:13:21 GMT
883   // 6e                                      | == Literal indexed ==
884   //                                         |   Indexed name (idx = 46)
885   //                                         |     location
886   // 91                                      |   Literal value (len = 23)
887   //                                         |     Huffman encoded:
888   // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C
889   // d3                                      | .
890   //                                         |     Decoded:
891   //                                         | https://www.example.com
892   //                                         | -> location: https://www.e
893   //                                         |    xample.com
894 
895   std::string first = absl::HexStringToBytes(
896       "488264025885aec3771a4b6196d07abe"
897       "941054d444a8200595040b8166e082a6"
898       "2d1bff6e919d29ad171863c78f0b97c8"
899       "e9ae82ae43d3");
900   const Http2HeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
901 
902   EXPECT_THAT(first_header_set,
903               ElementsAre(
904                   // clang-format off
905       Pair(":status", "302"),
906       Pair("cache-control", "private"),
907       Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
908       Pair("location", "https://www.example.com")));
909   // clang-format on
910 
911   expectEntry(62, 63, "location", "https://www.example.com");
912   expectEntry(63, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
913   expectEntry(64, 52, "cache-control", "private");
914   expectEntry(65, 42, ":status", "302");
915   EXPECT_EQ(222u, decoder_peer_.current_header_table_size());
916 
917   // 48                                      | == Literal indexed ==
918   //                                         |   Indexed name (idx = 8)
919   //                                         |     :status
920   // 83                                      |   Literal value (len = 3)
921   //                                         |     Huffman encoded:
922   // 640e ff                                 | d..
923   //                                         |     Decoded:
924   //                                         | 307
925   //                                         | - evict: :status: 302
926   //                                         | -> :status: 307
927   // c1                                      | == Indexed - Add ==
928   //                                         |   idx = 65
929   //                                         | -> cache-control: private
930   // c0                                      | == Indexed - Add ==
931   //                                         |   idx = 64
932   //                                         | -> date: Mon, 21 Oct 2013
933   //                                         |   20:13:21 GMT
934   // bf                                      | == Indexed - Add ==
935   //                                         |   idx = 63
936   //                                         | -> location:
937   //                                         |   https://www.example.com
938   std::string second = absl::HexStringToBytes("4883640effc1c0bf");
939   const Http2HeaderBlock& second_header_set =
940       DecodeBlockExpectingSuccess(second);
941 
942   EXPECT_THAT(second_header_set,
943               ElementsAre(
944                   // clang-format off
945       Pair(":status", "307"),
946       Pair("cache-control", "private"),
947       Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
948       Pair("location", "https://www.example.com")));
949   // clang-format on
950 
951   expectEntry(62, 42, ":status", "307");
952   expectEntry(63, 63, "location", "https://www.example.com");
953   expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
954   expectEntry(65, 52, "cache-control", "private");
955   EXPECT_EQ(222u, decoder_peer_.current_header_table_size());
956 
957   // 88                                      | == Indexed - Add ==
958   //                                         |   idx = 8
959   //                                         | -> :status: 200
960   // c1                                      | == Indexed - Add ==
961   //                                         |   idx = 65
962   //                                         | -> cache-control: private
963   // 61                                      | == Literal indexed ==
964   //                                         |   Indexed name (idx = 33)
965   //                                         |     date
966   // 96                                      |   Literal value (len = 22)
967   //                                         |     Huffman encoded:
968   // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
969   // e084 a62d 1bff                          | ...-..
970   //                                         |     Decoded:
971   //                                         | Mon, 21 Oct 2013 20:13:22
972   //                                         | GMT
973   //                                         | - evict: cache-control:
974   //                                         |   private
975   //                                         | -> date: Mon, 21 Oct 2013
976   //                                         |   20:13:22 GMT
977   // c0                                      | == Indexed - Add ==
978   //                                         |   idx = 64
979   //                                         | -> location:
980   //                                         |    https://www.example.com
981   // 5a                                      | == Literal indexed ==
982   //                                         |   Indexed name (idx = 26)
983   //                                         |     content-encoding
984   // 83                                      |   Literal value (len = 3)
985   //                                         |     Huffman encoded:
986   // 9bd9 ab                                 | ...
987   //                                         |     Decoded:
988   //                                         | gzip
989   //                                         | - evict: date: Mon, 21 Oct
990   //                                         |    2013 20:13:21 GMT
991   //                                         | -> content-encoding: gzip
992   // 77                                      | == Literal indexed ==
993   //                                         |   Indexed name (idx = 55)
994   //                                         |     set-cookie
995   // ad                                      |   Literal value (len = 45)
996   //                                         |     Huffman encoded:
997   // 94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9`
998   // d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)...
999   // 3160 65c0 03ed 4ee5 b106 3d50 07        | 1`e...N...=P.
1000   //                                         |     Decoded:
1001   //                                         | foo=ASDJKHQKBZXOQWEOPIUAXQ
1002   //                                         | WEOIU; max-age=3600; versi
1003   //                                         | on=1
1004   //                                         | - evict: location:
1005   //                                         |   https://www.example.com
1006   //                                         | - evict: :status: 307
1007   //                                         | -> set-cookie: foo=ASDJKHQ
1008   //                                         |   KBZXOQWEOPIUAXQWEOIU;
1009   //                                         |   max-age=3600; version=1
1010   std::string third = absl::HexStringToBytes(
1011       "88c16196d07abe941054d444a8200595"
1012       "040b8166e084a62d1bffc05a839bd9ab"
1013       "77ad94e7821dd7f2e6c7b335dfdfcd5b"
1014       "3960d5af27087f3672c1ab270fb5291f"
1015       "9587316065c003ed4ee5b1063d5007");
1016   const Http2HeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
1017 
1018   EXPECT_THAT(third_header_set,
1019               ElementsAre(
1020                   // clang-format off
1021       Pair(":status", "200"),
1022       Pair("cache-control", "private"),
1023       Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
1024       Pair("location", "https://www.example.com"),
1025       Pair("content-encoding", "gzip"),
1026       Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
1027            " max-age=3600; version=1")));
1028   // clang-format on
1029 
1030   expectEntry(62, 98, "set-cookie",
1031               "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
1032               " max-age=3600; version=1");
1033   expectEntry(63, 52, "content-encoding", "gzip");
1034   expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
1035   EXPECT_EQ(215u, decoder_peer_.current_header_table_size());
1036 }
1037 
1038 // Regression test: Found that entries with dynamic indexed names and literal
1039 // values caused "use after free" MSAN failures if the name was evicted as it
1040 // was being re-used.
TEST_P(HpackDecoderAdapterTest,ReuseNameOfEvictedEntry)1041 TEST_P(HpackDecoderAdapterTest, ReuseNameOfEvictedEntry) {
1042   // Each entry is measured as 32 bytes plus the sum of the lengths of the name
1043   // and the value. Set the size big enough for at most one entry, and a fairly
1044   // small one at that (31 ASCII characters).
1045   decoder_.ApplyHeaderTableSizeSetting(63);
1046 
1047   HpackBlockBuilder hbb;
1048   hbb.AppendDynamicTableSizeUpdate(0);
1049   hbb.AppendDynamicTableSizeUpdate(63);
1050 
1051   const absl::string_view name("some-name");
1052   const absl::string_view value1("some-value");
1053   const absl::string_view value2("another-value");
1054   const absl::string_view value3("yet-another-value");
1055 
1056   // Add an entry that will become the first in the dynamic table, entry 62.
1057   hbb.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, false,
1058                                 name, false, value1);
1059 
1060   // Confirm that entry has been added by re-using it.
1061   hbb.AppendIndexedHeader(62);
1062 
1063   // Add another entry referring to the name of the first. This will evict the
1064   // first.
1065   hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
1066                                      false, value2);
1067 
1068   // Confirm that entry has been added by re-using it.
1069   hbb.AppendIndexedHeader(62);
1070 
1071   // Add another entry referring to the name of the second. This will evict the
1072   // second.
1073   hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
1074                                      false, value3);
1075 
1076   // Confirm that entry has been added by re-using it.
1077   hbb.AppendIndexedHeader(62);
1078 
1079   // Can't have DecodeHeaderBlock do the default check for size of the decoded
1080   // data because Http2HeaderBlock will join multiple headers with the same
1081   // name into a single entry, thus we won't see repeated occurrences of the
1082   // name, instead seeing separators between values.
1083   EXPECT_TRUE(DecodeHeaderBlock(hbb.buffer(), kNoCheckDecodedSize));
1084 
1085   Http2HeaderBlock expected_header_set;
1086   expected_header_set.AppendValueOrAddHeader(name, value1);
1087   expected_header_set.AppendValueOrAddHeader(name, value1);
1088   expected_header_set.AppendValueOrAddHeader(name, value2);
1089   expected_header_set.AppendValueOrAddHeader(name, value2);
1090   expected_header_set.AppendValueOrAddHeader(name, value3);
1091   expected_header_set.AppendValueOrAddHeader(name, value3);
1092 
1093   // Http2HeaderBlock stores these 6 strings as '\0' separated values.
1094   // Make sure that is what happened.
1095   std::string joined_values = expected_header_set[name].as_string();
1096   EXPECT_EQ(joined_values.size(),
1097             2 * value1.size() + 2 * value2.size() + 2 * value3.size() + 5);
1098 
1099   EXPECT_EQ(expected_header_set, decoded_block());
1100 
1101   if (start_choice_ == START_WITH_HANDLER) {
1102     EXPECT_EQ(handler_.uncompressed_header_bytes(),
1103               6 * name.size() + 2 * value1.size() + 2 * value2.size() +
1104                   2 * value3.size());
1105   }
1106 }
1107 
1108 // Regression test for https://crbug.com/747395.
TEST_P(HpackDecoderAdapterTest,Cookies)1109 TEST_P(HpackDecoderAdapterTest, Cookies) {
1110   Http2HeaderBlock expected_header_set;
1111   expected_header_set["cookie"] = "foo; bar";
1112 
1113   EXPECT_TRUE(DecodeHeaderBlock(absl::HexStringToBytes("608294e76003626172")));
1114   EXPECT_EQ(expected_header_set, decoded_block());
1115 }
1116 
1117 }  // namespace
1118 }  // namespace test
1119 }  // namespace spdy
1120