• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/qpack/qpack_instruction_decoder.h"
6 
7 #include <algorithm>
8 
9 #include "absl/strings/escaping.h"
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/qpack/qpack_instructions.h"
12 #include "quiche/quic/platform/api/quic_logging.h"
13 #include "quiche/quic/platform/api/quic_test.h"
14 #include "quiche/quic/test_tools/qpack/qpack_test_utils.h"
15 
16 using ::testing::_;
17 using ::testing::Eq;
18 using ::testing::Expectation;
19 using ::testing::InvokeWithoutArgs;
20 using ::testing::Return;
21 using ::testing::StrictMock;
22 using ::testing::Values;
23 
24 namespace quic {
25 namespace test {
26 namespace {
27 
28 // This instruction has three fields: an S bit and two varints.
TestInstruction1()29 const QpackInstruction* TestInstruction1() {
30   static const QpackInstruction* const instruction =
31       new QpackInstruction{QpackInstructionOpcode{0x00, 0x80},
32                            {{QpackInstructionFieldType::kSbit, 0x40},
33                             {QpackInstructionFieldType::kVarint, 6},
34                             {QpackInstructionFieldType::kVarint2, 8}}};
35   return instruction;
36 }
37 
38 // This instruction has two fields: a header name with a 6-bit prefix, and a
39 // header value with a 7-bit prefix, both preceded by a Huffman bit.
TestInstruction2()40 const QpackInstruction* TestInstruction2() {
41   static const QpackInstruction* const instruction =
42       new QpackInstruction{QpackInstructionOpcode{0x80, 0x80},
43                            {{QpackInstructionFieldType::kName, 6},
44                             {QpackInstructionFieldType::kValue, 7}}};
45   return instruction;
46 }
47 
TestLanguage()48 const QpackLanguage* TestLanguage() {
49   static const QpackLanguage* const language =
50       new QpackLanguage{TestInstruction1(), TestInstruction2()};
51   return language;
52 }
53 
54 class MockDelegate : public QpackInstructionDecoder::Delegate {
55  public:
MockDelegate()56   MockDelegate() {
57     ON_CALL(*this, OnInstructionDecoded(_)).WillByDefault(Return(true));
58   }
59 
60   MockDelegate(const MockDelegate&) = delete;
61   MockDelegate& operator=(const MockDelegate&) = delete;
62   ~MockDelegate() override = default;
63 
64   MOCK_METHOD(bool, OnInstructionDecoded, (const QpackInstruction*),
65               (override));
66   MOCK_METHOD(void, OnInstructionDecodingError,
67               (QpackInstructionDecoder::ErrorCode error_code,
68                absl::string_view error_message),
69               (override));
70 };
71 
72 class QpackInstructionDecoderTest : public QuicTestWithParam<FragmentMode> {
73  protected:
QpackInstructionDecoderTest()74   QpackInstructionDecoderTest()
75       : decoder_(std::make_unique<QpackInstructionDecoder>(TestLanguage(),
76                                                            &delegate_)),
77         fragment_mode_(GetParam()) {}
78   ~QpackInstructionDecoderTest() override = default;
79 
SetUp()80   void SetUp() override {
81     // Destroy QpackInstructionDecoder on error to test that it does not crash.
82     // See https://crbug.com/1025209.
83     ON_CALL(delegate_, OnInstructionDecodingError(_, _))
84         .WillByDefault(InvokeWithoutArgs([this]() { decoder_.reset(); }));
85   }
86 
87   // Decode one full instruction with fragment sizes dictated by
88   // |fragment_mode_|.
89   // Assumes that |data| is a single complete instruction, and accordingly
90   // verifies that AtInstructionBoundary() returns true before and after the
91   // instruction, and returns false while decoding is in progress.
92   // Assumes that delegate methods destroy |decoder_| if they return false.
DecodeInstruction(absl::string_view data)93   void DecodeInstruction(absl::string_view data) {
94     EXPECT_TRUE(decoder_->AtInstructionBoundary());
95 
96     FragmentSizeGenerator fragment_size_generator =
97         FragmentModeToFragmentSizeGenerator(fragment_mode_);
98 
99     while (!data.empty()) {
100       size_t fragment_size = std::min(fragment_size_generator(), data.size());
101       bool success = decoder_->Decode(data.substr(0, fragment_size));
102       if (!decoder_) {
103         EXPECT_FALSE(success);
104         return;
105       }
106       EXPECT_TRUE(success);
107       data = data.substr(fragment_size);
108       if (!data.empty()) {
109         EXPECT_FALSE(decoder_->AtInstructionBoundary());
110       }
111     }
112 
113     EXPECT_TRUE(decoder_->AtInstructionBoundary());
114   }
115 
116   StrictMock<MockDelegate> delegate_;
117   std::unique_ptr<QpackInstructionDecoder> decoder_;
118 
119  private:
120   const FragmentMode fragment_mode_;
121 };
122 
123 INSTANTIATE_TEST_SUITE_P(All, QpackInstructionDecoderTest,
124                          Values(FragmentMode::kSingleChunk,
125                                 FragmentMode::kOctetByOctet));
126 
TEST_P(QpackInstructionDecoderTest,SBitAndVarint2)127 TEST_P(QpackInstructionDecoderTest, SBitAndVarint2) {
128   EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()));
129   DecodeInstruction(absl::HexStringToBytes("7f01ff65"));
130 
131   EXPECT_TRUE(decoder_->s_bit());
132   EXPECT_EQ(64u, decoder_->varint());
133   EXPECT_EQ(356u, decoder_->varint2());
134 
135   EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()));
136   DecodeInstruction(absl::HexStringToBytes("05c8"));
137 
138   EXPECT_FALSE(decoder_->s_bit());
139   EXPECT_EQ(5u, decoder_->varint());
140   EXPECT_EQ(200u, decoder_->varint2());
141 }
142 
TEST_P(QpackInstructionDecoderTest,NameAndValue)143 TEST_P(QpackInstructionDecoderTest, NameAndValue) {
144   EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
145   DecodeInstruction(absl::HexStringToBytes("83666f6f03626172"));
146 
147   EXPECT_EQ("foo", decoder_->name());
148   EXPECT_EQ("bar", decoder_->value());
149 
150   EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
151   DecodeInstruction(absl::HexStringToBytes("8000"));
152 
153   EXPECT_EQ("", decoder_->name());
154   EXPECT_EQ("", decoder_->value());
155 
156   EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
157   DecodeInstruction(absl::HexStringToBytes("c294e7838c767f"));
158 
159   EXPECT_EQ("foo", decoder_->name());
160   EXPECT_EQ("bar", decoder_->value());
161 }
162 
TEST_P(QpackInstructionDecoderTest,InvalidHuffmanEncoding)163 TEST_P(QpackInstructionDecoderTest, InvalidHuffmanEncoding) {
164   EXPECT_CALL(delegate_,
165               OnInstructionDecodingError(
166                   QpackInstructionDecoder::ErrorCode::HUFFMAN_ENCODING_ERROR,
167                   Eq("Error in Huffman-encoded string.")));
168   DecodeInstruction(absl::HexStringToBytes("c1ff"));
169 }
170 
TEST_P(QpackInstructionDecoderTest,InvalidVarintEncoding)171 TEST_P(QpackInstructionDecoderTest, InvalidVarintEncoding) {
172   EXPECT_CALL(delegate_,
173               OnInstructionDecodingError(
174                   QpackInstructionDecoder::ErrorCode::INTEGER_TOO_LARGE,
175                   Eq("Encoded integer too large.")));
176   DecodeInstruction(absl::HexStringToBytes("ffffffffffffffffffffff"));
177 }
178 
TEST_P(QpackInstructionDecoderTest,StringLiteralTooLong)179 TEST_P(QpackInstructionDecoderTest, StringLiteralTooLong) {
180   EXPECT_CALL(delegate_,
181               OnInstructionDecodingError(
182                   QpackInstructionDecoder::ErrorCode::STRING_LITERAL_TOO_LONG,
183                   Eq("String literal too long.")));
184   DecodeInstruction(absl::HexStringToBytes("bfffff7f"));
185 }
186 
TEST_P(QpackInstructionDecoderTest,DelegateSignalsError)187 TEST_P(QpackInstructionDecoderTest, DelegateSignalsError) {
188   // First instruction is valid.
189   Expectation first_call =
190       EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()))
191           .WillOnce(InvokeWithoutArgs([this]() -> bool {
192             EXPECT_EQ(1u, decoder_->varint());
193             return true;
194           }));
195 
196   // Second instruction is invalid.  Decoding must halt.
197   EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()))
198       .After(first_call)
199       .WillOnce(InvokeWithoutArgs([this]() -> bool {
200         EXPECT_EQ(2u, decoder_->varint());
201         return false;
202       }));
203 
204   EXPECT_FALSE(
205       decoder_->Decode(absl::HexStringToBytes("01000200030004000500")));
206 }
207 
208 // QpackInstructionDecoder must not crash if it is destroyed from a
209 // Delegate::OnInstructionDecoded() call as long as it returns false.
TEST_P(QpackInstructionDecoderTest,DelegateSignalsErrorAndDestroysDecoder)210 TEST_P(QpackInstructionDecoderTest, DelegateSignalsErrorAndDestroysDecoder) {
211   EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()))
212       .WillOnce(InvokeWithoutArgs([this]() -> bool {
213         EXPECT_EQ(1u, decoder_->varint());
214         decoder_.reset();
215         return false;
216       }));
217   DecodeInstruction(absl::HexStringToBytes("0100"));
218 }
219 
220 }  // namespace
221 }  // namespace test
222 }  // namespace quic
223