OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/hpack/hpack_input_stream.h" | 5 #include "net/spdy/hpack/hpack_input_stream.h" |
6 | 6 |
7 #include <bitset> | 7 #include <bitset> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
13 #include "net/spdy/hpack/hpack_constants.h" | 13 #include "net/spdy/hpack/hpack_constants.h" |
14 #include "net/spdy/spdy_test_utils.h" | 14 #include "net/spdy/spdy_test_utils.h" |
15 #include "net/test/gtest_util.h" | 15 #include "net/test/gtest_util.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 | 17 |
18 namespace net { | 18 namespace net { |
19 | 19 |
20 namespace { | 20 namespace test { |
21 | 21 |
22 using base::StringPiece; | 22 using base::StringPiece; |
23 using std::string; | 23 using std::string; |
24 using test::a2b_hex; | 24 using test::a2b_hex; |
25 | 25 |
26 const size_t kLiteralBound = 1024; | 26 const size_t kLiteralBound = 1024; |
27 | 27 |
28 // Hex representation of encoded length and Huffman string. | 28 // Hex representation of encoded length and Huffman string. |
29 const char kEncodedHuffmanFixture[] = | 29 const char kEncodedHuffmanFixture[] = |
30 "2d" // Length prefix. | 30 "2d" // Length prefix. |
31 "94e7821dd7f2e6c7b335dfdfcd5b3960" | 31 "94e7821dd7f2e6c7b335dfdfcd5b3960" |
32 "d5af27087f3672c1ab270fb5291f9587" | 32 "d5af27087f3672c1ab270fb5291f9587" |
33 "316065c003ed4ee5b1063d5007"; | 33 "316065c003ed4ee5b1063d5007"; |
34 | 34 |
35 const char kDecodedHuffmanFixture[] = | 35 const char kDecodedHuffmanFixture[] = |
36 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"; | 36 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"; |
37 | 37 |
| 38 class HpackInputStreamPeer { |
| 39 public: |
| 40 explicit HpackInputStreamPeer(HpackInputStream* input_stream) |
| 41 : input_stream_(input_stream) {} |
| 42 |
| 43 void SetBitOffsetForTest(size_t bit_offset) { |
| 44 input_stream_->bit_offset_ = bit_offset; |
| 45 } |
| 46 |
| 47 uint32_t ParsedBytesCurrent() { return input_stream_->parsed_bytes_current_; } |
| 48 |
| 49 private: |
| 50 HpackInputStream* input_stream_; |
| 51 }; |
| 52 |
38 // Utility function to decode an assumed-valid uint32_t with an N-bit | 53 // Utility function to decode an assumed-valid uint32_t with an N-bit |
39 // prefix. | 54 // prefix. |
40 uint32_t DecodeValidUint32(uint8_t N, StringPiece str) { | 55 uint32_t DecodeValidUint32(uint8_t N, StringPiece str) { |
41 EXPECT_GT(N, 0); | 56 EXPECT_GT(N, 0); |
42 EXPECT_LE(N, 8); | 57 EXPECT_LE(N, 8); |
43 HpackInputStream input_stream(kLiteralBound, str); | 58 HpackInputStream input_stream(kLiteralBound, str); |
44 input_stream.SetBitOffsetForTest(8 - N); | 59 HpackInputStreamPeer input_stream_peer(&input_stream); |
| 60 input_stream_peer.SetBitOffsetForTest(8 - N); |
45 uint32_t I; | 61 uint32_t I; |
46 EXPECT_TRUE(input_stream.DecodeNextUint32(&I)); | 62 EXPECT_TRUE(input_stream.DecodeNextUint32(&I)); |
| 63 EXPECT_EQ(str.size(), input_stream_peer.ParsedBytesCurrent()); |
| 64 EXPECT_FALSE(input_stream.NeedMoreData()); |
47 return I; | 65 return I; |
48 } | 66 } |
49 | 67 |
50 // Utility function to decode an assumed-invalid uint32_t with an N-bit | 68 // Utility function to decode an assumed-invalid uint32_t with an N-bit |
51 // prefix. | 69 // prefix. |
52 void ExpectDecodeUint32Invalid(uint8_t N, StringPiece str) { | 70 void ExpectDecodeUint32Invalid(uint8_t N, StringPiece str) { |
53 EXPECT_GT(N, 0); | 71 EXPECT_GT(N, 0); |
54 EXPECT_LE(N, 8); | 72 EXPECT_LE(N, 8); |
55 HpackInputStream input_stream(kLiteralBound, str); | 73 HpackInputStream input_stream(kLiteralBound, str); |
56 input_stream.SetBitOffsetForTest(8 - N); | 74 HpackInputStreamPeer input_stream_peer(&input_stream); |
| 75 input_stream_peer.SetBitOffsetForTest(8 - N); |
57 uint32_t I; | 76 uint32_t I; |
58 EXPECT_FALSE(input_stream.DecodeNextUint32(&I)); | 77 EXPECT_FALSE(input_stream.DecodeNextUint32(&I)); |
59 } | 78 } |
60 | 79 |
61 uint32_t bits32(const string& bitstring) { | 80 uint32_t bits32(const string& bitstring) { |
62 return std::bitset<32>(bitstring).to_ulong(); | 81 return std::bitset<32>(bitstring).to_ulong(); |
63 } | 82 } |
64 | 83 |
65 // The {Number}ByteIntegersEightBitPrefix tests below test that | 84 // The {Number}ByteIntegersEightBitPrefix tests below test that |
66 // certain integers are decoded correctly with an 8-bit prefix in | 85 // certain integers are decoded correctly with an 8-bit prefix in |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 ExpectDecodeUint32Invalid(2, "\x03\x80\x80\x80\x80\x80\x01"); | 490 ExpectDecodeUint32Invalid(2, "\x03\x80\x80\x80\x80\x80\x01"); |
472 ExpectDecodeUint32Invalid(2, "\xff\xff\xff\xff\xff\xff\xff"); | 491 ExpectDecodeUint32Invalid(2, "\xff\xff\xff\xff\xff\xff\xff"); |
473 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x00"); | 492 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x00"); |
474 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x01"); | 493 ExpectDecodeUint32Invalid(1, "\x01\x80\x80\x80\x80\x80\x01"); |
475 ExpectDecodeUint32Invalid(1, "\xff\xff\xff\xff\xff\xff\xff"); | 494 ExpectDecodeUint32Invalid(1, "\xff\xff\xff\xff\xff\xff\xff"); |
476 } | 495 } |
477 | 496 |
478 // Decoding a valid encoded string literal should work. | 497 // Decoding a valid encoded string literal should work. |
479 TEST(HpackInputStreamTest, DecodeNextIdentityString) { | 498 TEST(HpackInputStreamTest, DecodeNextIdentityString) { |
480 HpackInputStream input_stream(kLiteralBound, "\x0estring literal"); | 499 HpackInputStream input_stream(kLiteralBound, "\x0estring literal"); |
| 500 HpackInputStreamPeer input_stream_peer(&input_stream); |
481 | 501 |
482 EXPECT_TRUE(input_stream.HasMoreData()); | 502 EXPECT_TRUE(input_stream.HasMoreData()); |
483 StringPiece string_piece; | 503 StringPiece string_piece; |
484 EXPECT_TRUE(input_stream.DecodeNextIdentityString(&string_piece)); | 504 EXPECT_TRUE(input_stream.DecodeNextIdentityString(&string_piece)); |
485 EXPECT_EQ("string literal", string_piece); | 505 EXPECT_EQ("string literal", string_piece); |
486 EXPECT_FALSE(input_stream.HasMoreData()); | 506 EXPECT_FALSE(input_stream.HasMoreData()); |
| 507 EXPECT_EQ(string_piece.size() + 1, input_stream_peer.ParsedBytesCurrent()); |
| 508 EXPECT_FALSE(input_stream.NeedMoreData()); |
487 } | 509 } |
488 | 510 |
489 // Decoding an encoded string literal with size larger than | 511 // Decoding an encoded string literal with size larger than |
490 // |max_string_literal_size_| should fail. | 512 // |max_string_literal_size_| should fail. |
491 TEST(HpackInputStreamTest, DecodeNextIdentityStringSizeLimit) { | 513 TEST(HpackInputStreamTest, DecodeNextIdentityStringSizeLimit) { |
492 HpackInputStream input_stream(13, "\x0estring literal"); | 514 HpackInputStream input_stream(13, "\x0estring literal"); |
493 | 515 |
494 EXPECT_TRUE(input_stream.HasMoreData()); | 516 EXPECT_TRUE(input_stream.HasMoreData()); |
495 StringPiece string_piece; | 517 StringPiece string_piece; |
496 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece)); | 518 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece)); |
| 519 EXPECT_FALSE(input_stream.NeedMoreData()); |
497 } | 520 } |
498 | 521 |
499 // Decoding an encoded string literal with size larger than the | 522 // Decoding an encoded string literal with size larger than the |
500 // remainder of the buffer should fail. | 523 // remainder of the buffer should fail. |
501 TEST(HpackInputStreamTest, DecodeNextIdentityStringNotEnoughInput) { | 524 TEST(HpackInputStreamTest, DecodeNextIdentityStringNotEnoughInput) { |
502 // Set the length to be one more than it should be. | 525 // Set the length to be one more than it should be. |
503 HpackInputStream input_stream(kLiteralBound, "\x0fstring literal"); | 526 HpackInputStream input_stream(kLiteralBound, "\x0fstring literal"); |
504 | 527 |
505 EXPECT_TRUE(input_stream.HasMoreData()); | 528 EXPECT_TRUE(input_stream.HasMoreData()); |
506 StringPiece string_piece; | 529 StringPiece string_piece; |
507 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece)); | 530 EXPECT_FALSE(input_stream.DecodeNextIdentityString(&string_piece)); |
| 531 EXPECT_TRUE(input_stream.NeedMoreData()); |
508 } | 532 } |
509 | 533 |
510 TEST(HpackInputStreamTest, DecodeNextHuffmanString) { | 534 TEST(HpackInputStreamTest, DecodeNextHuffmanString) { |
511 string output, input(a2b_hex(kEncodedHuffmanFixture)); | 535 string output, input(a2b_hex(kEncodedHuffmanFixture)); |
512 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input); | 536 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input); |
| 537 HpackInputStreamPeer input_stream_peer(&input_stream); |
513 | 538 |
514 EXPECT_TRUE(input_stream.HasMoreData()); | 539 EXPECT_TRUE(input_stream.HasMoreData()); |
515 EXPECT_TRUE(input_stream.DecodeNextHuffmanString(&output)); | 540 EXPECT_TRUE(input_stream.DecodeNextHuffmanString(&output)); |
516 EXPECT_EQ(kDecodedHuffmanFixture, output); | 541 EXPECT_EQ(kDecodedHuffmanFixture, output); |
517 EXPECT_FALSE(input_stream.HasMoreData()); | 542 EXPECT_FALSE(input_stream.HasMoreData()); |
| 543 EXPECT_FALSE(input_stream.NeedMoreData()); |
| 544 EXPECT_EQ(46u, input_stream_peer.ParsedBytesCurrent()); |
518 } | 545 } |
519 | 546 |
520 TEST(HpackInputStreamTest, DecodeNextHuffmanStringSizeLimit) { | 547 TEST(HpackInputStreamTest, DecodeNextHuffmanStringSizeLimit) { |
521 string output, input(a2b_hex(kEncodedHuffmanFixture)); | 548 string output, input(a2b_hex(kEncodedHuffmanFixture)); |
522 // Max string literal is one byte shorter than the decoded fixture. | 549 // Max string literal is one byte shorter than the decoded fixture. |
523 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 2, input); | 550 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 2, input); |
524 | 551 |
525 // Decoded string overflows the max string literal. | 552 // Decoded string overflows the max string literal. |
526 EXPECT_TRUE(input_stream.HasMoreData()); | 553 EXPECT_TRUE(input_stream.HasMoreData()); |
527 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output)); | 554 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output)); |
| 555 EXPECT_FALSE(input_stream.NeedMoreData()); |
528 } | 556 } |
529 | 557 |
530 TEST(HpackInputStreamTest, DecodeNextHuffmanStringNotEnoughInput) { | 558 TEST(HpackInputStreamTest, DecodeNextHuffmanStringNotEnoughInput) { |
531 string output, input(a2b_hex(kEncodedHuffmanFixture)); | 559 string output, input(a2b_hex(kEncodedHuffmanFixture)); |
532 input[0]++; // Input prefix is one byte larger than available input. | 560 input[0]++; // Input prefix is one byte larger than available input. |
533 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input); | 561 HpackInputStream input_stream(arraysize(kDecodedHuffmanFixture) - 1, input); |
534 | 562 |
535 // Not enough buffer for declared encoded length. | 563 // Not enough buffer for declared encoded length. |
536 EXPECT_TRUE(input_stream.HasMoreData()); | 564 EXPECT_TRUE(input_stream.HasMoreData()); |
537 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output)); | 565 EXPECT_FALSE(input_stream.DecodeNextHuffmanString(&output)); |
| 566 EXPECT_TRUE(input_stream.NeedMoreData()); |
538 } | 567 } |
539 | 568 |
540 TEST(HpackInputStreamTest, PeekBitsAndConsume) { | 569 TEST(HpackInputStreamTest, PeekBitsAndConsume) { |
541 HpackInputStream input_stream(kLiteralBound, "\xad\xab\xad\xab\xad"); | 570 HpackInputStream input_stream(kLiteralBound, "\xad\xab\xad\xab\xad"); |
542 | 571 |
543 uint32_t bits = 0; | 572 uint32_t bits = 0; |
544 size_t peeked_count = 0; | 573 size_t peeked_count = 0; |
545 | 574 |
546 // Read 0xad. | 575 // Read 0xad. |
547 EXPECT_TRUE(input_stream.PeekBits(&peeked_count, &bits)); | 576 EXPECT_TRUE(input_stream.PeekBits(&peeked_count, &bits)); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 input_stream.ConsumeBits(3); | 727 input_stream.ConsumeBits(3); |
699 input_stream.ConsumeByteRemainder(); | 728 input_stream.ConsumeByteRemainder(); |
700 EXPECT_TRUE(input_stream.HasMoreData()); | 729 EXPECT_TRUE(input_stream.HasMoreData()); |
701 | 730 |
702 input_stream.ConsumeBits(6); | 731 input_stream.ConsumeBits(6); |
703 EXPECT_TRUE(input_stream.HasMoreData()); | 732 EXPECT_TRUE(input_stream.HasMoreData()); |
704 input_stream.ConsumeByteRemainder(); | 733 input_stream.ConsumeByteRemainder(); |
705 EXPECT_FALSE(input_stream.HasMoreData()); | 734 EXPECT_FALSE(input_stream.HasMoreData()); |
706 } | 735 } |
707 | 736 |
708 } // namespace | 737 TEST(HpackInputStreamTest, IncompleteHeaderMatchPrefixAndConsume) { |
| 738 HpackInputStream input_stream(kLiteralBound, ""); |
| 739 HpackInputStreamPeer input_stream_peer(&input_stream); |
| 740 EXPECT_FALSE(input_stream.MatchPrefixAndConsume(kIndexedOpcode)); |
| 741 EXPECT_EQ(0u, input_stream_peer.ParsedBytesCurrent()); |
| 742 EXPECT_TRUE(input_stream.NeedMoreData()); |
| 743 } |
| 744 |
| 745 TEST(HpackInputStreamTest, IncompleteHeaderDecodeNextUint32) { |
| 746 // First byte only |
| 747 HpackInputStream input_stream1(kLiteralBound, "\xff"); |
| 748 HpackInputStreamPeer input_stream1_peer(&input_stream1); |
| 749 EXPECT_TRUE(input_stream1.MatchPrefixAndConsume(kIndexedOpcode)); |
| 750 uint32_t result; |
| 751 EXPECT_FALSE(input_stream1.DecodeNextUint32(&result)); |
| 752 EXPECT_TRUE(input_stream1.NeedMoreData()); |
| 753 EXPECT_EQ(1u, input_stream1_peer.ParsedBytesCurrent()); |
| 754 |
| 755 // No last byte |
| 756 HpackInputStream input_stream2(kLiteralBound, "\xff\x80\x80\x80"); |
| 757 HpackInputStreamPeer input_stream2_peer(&input_stream2); |
| 758 EXPECT_TRUE(input_stream2.MatchPrefixAndConsume(kIndexedOpcode)); |
| 759 EXPECT_FALSE(input_stream2.DecodeNextUint32(&result)); |
| 760 EXPECT_TRUE(input_stream2.NeedMoreData()); |
| 761 EXPECT_EQ(4u, input_stream2_peer.ParsedBytesCurrent()); |
| 762 |
| 763 // Error happens before finishing parsing. |
| 764 HpackInputStream input_stream3(kLiteralBound, "\xff\xff\xff\xff\xff\xff\xff"); |
| 765 HpackInputStreamPeer input_stream3_peer(&input_stream3); |
| 766 EXPECT_TRUE(input_stream3.MatchPrefixAndConsume(kIndexedOpcode)); |
| 767 EXPECT_FALSE(input_stream3.DecodeNextUint32(&result)); |
| 768 EXPECT_FALSE(input_stream3.NeedMoreData()); |
| 769 EXPECT_EQ(6u, input_stream3_peer.ParsedBytesCurrent()); |
| 770 } |
| 771 |
| 772 TEST(HpackInputStreamTest, IncompleteHeaderDecodeNextIdentityString) { |
| 773 HpackInputStream input_stream1(kLiteralBound, "\x0estring litera"); |
| 774 HpackInputStreamPeer input_stream1_peer(&input_stream1); |
| 775 StringPiece string_piece; |
| 776 EXPECT_FALSE(input_stream1.DecodeNextIdentityString(&string_piece)); |
| 777 // Only parsed first byte. |
| 778 EXPECT_EQ(1u, input_stream1_peer.ParsedBytesCurrent()); |
| 779 EXPECT_TRUE(input_stream1.NeedMoreData()); |
| 780 |
| 781 HpackInputStream input_stream2(kLiteralBound, "\x0e"); |
| 782 HpackInputStreamPeer input_stream2_peer(&input_stream2); |
| 783 EXPECT_FALSE(input_stream2.DecodeNextIdentityString(&string_piece)); |
| 784 // Only parsed first byte. |
| 785 EXPECT_EQ(1u, input_stream2_peer.ParsedBytesCurrent()); |
| 786 EXPECT_TRUE(input_stream2.NeedMoreData()); |
| 787 } |
| 788 |
| 789 TEST(HpackInputStreamTest, IncompleteHeaderDecodeNextHuffmanString) { |
| 790 string output, input(a2b_hex(kEncodedHuffmanFixture)); |
| 791 input.resize(input.size() - 1); // Remove last byte. |
| 792 HpackInputStream input_stream1(arraysize(kDecodedHuffmanFixture) - 1, input); |
| 793 HpackInputStreamPeer input_stream1_peer(&input_stream1); |
| 794 EXPECT_FALSE(input_stream1.DecodeNextHuffmanString(&output)); |
| 795 EXPECT_EQ(1u, input_stream1_peer.ParsedBytesCurrent()); |
| 796 EXPECT_TRUE(input_stream1.NeedMoreData()); |
| 797 |
| 798 input.erase(1, input.size()); // Remove all bytes except the first one. |
| 799 HpackInputStream input_stream2(arraysize(kDecodedHuffmanFixture) - 1, input); |
| 800 HpackInputStreamPeer input_stream2_peer(&input_stream2); |
| 801 EXPECT_FALSE(input_stream2.DecodeNextHuffmanString(&output)); |
| 802 EXPECT_EQ(1u, input_stream2_peer.ParsedBytesCurrent()); |
| 803 EXPECT_TRUE(input_stream2.NeedMoreData()); |
| 804 } |
| 805 |
| 806 } // namespace test |
709 | 807 |
710 } // namespace net | 808 } // namespace net |
OLD | NEW |