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