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