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