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