1 // Copyright 2016 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/http2/decoder/decode_http2_structures.h"
6
7 // Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined
8 // in quiche/http2/http2_structures.h).
9
10 #include <stddef.h>
11
12 #include <string>
13
14 #include "absl/strings/string_view.h"
15 #include "quiche/http2/decoder/decode_buffer.h"
16 #include "quiche/http2/decoder/decode_status.h"
17 #include "quiche/http2/http2_constants.h"
18 #include "quiche/http2/test_tools/http2_frame_builder.h"
19 #include "quiche/http2/test_tools/http2_random.h"
20 #include "quiche/http2/test_tools/http2_structures_test_util.h"
21 #include "quiche/common/platform/api/quiche_logging.h"
22 #include "quiche/common/platform/api/quiche_test.h"
23
24 namespace http2 {
25 namespace test {
26 namespace {
27
28 template <typename T, size_t N>
ToStringPiece(T (& data)[N])29 absl::string_view ToStringPiece(T (&data)[N]) {
30 return absl::string_view(reinterpret_cast<const char*>(data), N * sizeof(T));
31 }
32
33 template <class S>
SerializeStructure(const S & s)34 std::string SerializeStructure(const S& s) {
35 Http2FrameBuilder fb;
36 fb.Append(s);
37 EXPECT_EQ(S::EncodedSize(), fb.size());
38 return fb.buffer();
39 }
40
41 template <class S>
42 class StructureDecoderTest : public quiche::test::QuicheTest {
43 protected:
44 typedef S Structure;
45
StructureDecoderTest()46 StructureDecoderTest() : random_(), random_decode_count_(100) {}
47
48 // Set the fields of |*p| to random values.
Randomize(S * p)49 void Randomize(S* p) { ::http2::test::Randomize(p, &random_); }
50
51 // Fully decodes the Structure at the start of data, and confirms it matches
52 // *expected (if provided).
DecodeLeadingStructure(const S * expected,absl::string_view data)53 void DecodeLeadingStructure(const S* expected, absl::string_view data) {
54 ASSERT_LE(S::EncodedSize(), data.size());
55 DecodeBuffer db(data);
56 Randomize(&structure_);
57 DoDecode(&structure_, &db);
58 EXPECT_EQ(db.Offset(), S::EncodedSize());
59 if (expected != nullptr) {
60 EXPECT_EQ(structure_, *expected);
61 }
62 }
63
64 template <size_t N>
DecodeLeadingStructure(const char (& data)[N])65 void DecodeLeadingStructure(const char (&data)[N]) {
66 DecodeLeadingStructure(nullptr, absl::string_view(data, N));
67 }
68
69 // Encode the structure |in_s| into bytes, then decode the bytes
70 // and validate that the decoder produced the same field values.
EncodeThenDecode(const S & in_s)71 void EncodeThenDecode(const S& in_s) {
72 std::string bytes = SerializeStructure(in_s);
73 EXPECT_EQ(S::EncodedSize(), bytes.size());
74 DecodeLeadingStructure(&in_s, bytes);
75 }
76
77 // Generate
TestDecodingRandomizedStructures(size_t count)78 void TestDecodingRandomizedStructures(size_t count) {
79 for (size_t i = 0; i < count && !HasFailure(); ++i) {
80 Structure input;
81 Randomize(&input);
82 EncodeThenDecode(input);
83 }
84 }
85
TestDecodingRandomizedStructures()86 void TestDecodingRandomizedStructures() {
87 TestDecodingRandomizedStructures(random_decode_count_);
88 }
89
90 Http2Random random_;
91 const size_t random_decode_count_;
92 uint32_t decode_offset_ = 0;
93 S structure_;
94 size_t fast_decode_count_ = 0;
95 size_t slow_decode_count_ = 0;
96 };
97
98 class FrameHeaderDecoderTest : public StructureDecoderTest<Http2FrameHeader> {};
99
TEST_F(FrameHeaderDecoderTest,DecodesLiteral)100 TEST_F(FrameHeaderDecoderTest, DecodesLiteral) {
101 {
102 // Realistic input.
103 const char kData[] = {
104 '\x00', '\x00', '\x05', // Payload length: 5
105 '\x01', // Frame type: HEADERS
106 '\x08', // Flags: PADDED
107 '\x00', '\x00', '\x00', '\x01', // Stream ID: 1
108 '\x04', // Padding length: 4
109 '\x00', '\x00', '\x00', '\x00', // Padding bytes
110 };
111 DecodeLeadingStructure(kData);
112 if (!HasFailure()) {
113 EXPECT_EQ(5u, structure_.payload_length);
114 EXPECT_EQ(Http2FrameType::HEADERS, structure_.type);
115 EXPECT_EQ(Http2FrameFlag::PADDED, structure_.flags);
116 EXPECT_EQ(1u, structure_.stream_id);
117 }
118 }
119 {
120 // Unlikely input.
121 const char kData[] = {
122 '\xff', '\xff', '\xff', // Payload length: uint24 max
123 '\xff', // Frame type: Unknown
124 '\xff', // Flags: Unknown/All
125 '\xff', '\xff', '\xff', '\xff', // Stream ID: uint31 max, plus R-bit
126 };
127 DecodeLeadingStructure(kData);
128 if (!HasFailure()) {
129 EXPECT_EQ((1u << 24) - 1, structure_.payload_length);
130 EXPECT_EQ(static_cast<Http2FrameType>(255), structure_.type);
131 EXPECT_EQ(255, structure_.flags);
132 EXPECT_EQ(0x7FFFFFFFu, structure_.stream_id);
133 }
134 }
135 }
136
TEST_F(FrameHeaderDecoderTest,DecodesRandomized)137 TEST_F(FrameHeaderDecoderTest, DecodesRandomized) {
138 TestDecodingRandomizedStructures();
139 }
140
141 //------------------------------------------------------------------------------
142
143 class PriorityFieldsDecoderTest
144 : public StructureDecoderTest<Http2PriorityFields> {};
145
TEST_F(PriorityFieldsDecoderTest,DecodesLiteral)146 TEST_F(PriorityFieldsDecoderTest, DecodesLiteral) {
147 {
148 const char kData[] = {
149 '\x80', '\x00', '\x00', '\x05', // Exclusive (yes) and Dependency (5)
150 '\xff', // Weight: 256 (after adding 1)
151 };
152 DecodeLeadingStructure(kData);
153 if (!HasFailure()) {
154 EXPECT_EQ(5u, structure_.stream_dependency);
155 EXPECT_EQ(256u, structure_.weight);
156 EXPECT_EQ(true, structure_.is_exclusive);
157 }
158 }
159 {
160 const char kData[] = {
161 '\x7f', '\xff',
162 '\xff', '\xff', // Exclusive (no) and Dependency (0x7fffffff)
163 '\x00', // Weight: 1 (after adding 1)
164 };
165 DecodeLeadingStructure(kData);
166 if (!HasFailure()) {
167 EXPECT_EQ(StreamIdMask(), structure_.stream_dependency);
168 EXPECT_EQ(1u, structure_.weight);
169 EXPECT_FALSE(structure_.is_exclusive);
170 }
171 }
172 }
173
TEST_F(PriorityFieldsDecoderTest,DecodesRandomized)174 TEST_F(PriorityFieldsDecoderTest, DecodesRandomized) {
175 TestDecodingRandomizedStructures();
176 }
177
178 //------------------------------------------------------------------------------
179
180 class RstStreamFieldsDecoderTest
181 : public StructureDecoderTest<Http2RstStreamFields> {};
182
TEST_F(RstStreamFieldsDecoderTest,DecodesLiteral)183 TEST_F(RstStreamFieldsDecoderTest, DecodesLiteral) {
184 {
185 const char kData[] = {
186 '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR
187 };
188 DecodeLeadingStructure(kData);
189 if (!HasFailure()) {
190 EXPECT_TRUE(structure_.IsSupportedErrorCode());
191 EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_.error_code);
192 }
193 }
194 {
195 const char kData[] = {
196 '\xff', '\xff', '\xff',
197 '\xff', // Error: max uint32 (Unknown error code)
198 };
199 DecodeLeadingStructure(kData);
200 if (!HasFailure()) {
201 EXPECT_FALSE(structure_.IsSupportedErrorCode());
202 EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code);
203 }
204 }
205 }
206
TEST_F(RstStreamFieldsDecoderTest,DecodesRandomized)207 TEST_F(RstStreamFieldsDecoderTest, DecodesRandomized) {
208 TestDecodingRandomizedStructures();
209 }
210
211 //------------------------------------------------------------------------------
212
213 class SettingFieldsDecoderTest
214 : public StructureDecoderTest<Http2SettingFields> {};
215
TEST_F(SettingFieldsDecoderTest,DecodesLiteral)216 TEST_F(SettingFieldsDecoderTest, DecodesLiteral) {
217 {
218 const char kData[] = {
219 '\x00', '\x01', // Setting: HEADER_TABLE_SIZE
220 '\x00', '\x00', '\x40', '\x00', // Value: 16K
221 };
222 DecodeLeadingStructure(kData);
223 if (!HasFailure()) {
224 EXPECT_TRUE(structure_.IsSupportedParameter());
225 EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE,
226 structure_.parameter);
227 EXPECT_EQ(1u << 14, structure_.value);
228 }
229 }
230 {
231 const char kData[] = {
232 '\x00', '\x00', // Setting: Unknown (0)
233 '\xff', '\xff', '\xff', '\xff', // Value: max uint32
234 };
235 DecodeLeadingStructure(kData);
236 if (!HasFailure()) {
237 EXPECT_FALSE(structure_.IsSupportedParameter());
238 EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_.parameter);
239 }
240 }
241 }
242
TEST_F(SettingFieldsDecoderTest,DecodesRandomized)243 TEST_F(SettingFieldsDecoderTest, DecodesRandomized) {
244 TestDecodingRandomizedStructures();
245 }
246
247 //------------------------------------------------------------------------------
248
249 class PushPromiseFieldsDecoderTest
250 : public StructureDecoderTest<Http2PushPromiseFields> {};
251
TEST_F(PushPromiseFieldsDecoderTest,DecodesLiteral)252 TEST_F(PushPromiseFieldsDecoderTest, DecodesLiteral) {
253 {
254 const char kData[] = {
255 '\x00', '\x01', '\x8a', '\x92', // Promised Stream ID: 101010
256 };
257 DecodeLeadingStructure(kData);
258 if (!HasFailure()) {
259 EXPECT_EQ(101010u, structure_.promised_stream_id);
260 }
261 }
262 {
263 // Promised stream id has R-bit (reserved for future use) set, which
264 // should be cleared by the decoder.
265 const char kData[] = {
266 '\xff', '\xff', '\xff',
267 '\xff', // Promised Stream ID: max uint31 and R-bit
268 };
269 DecodeLeadingStructure(kData);
270 if (!HasFailure()) {
271 EXPECT_EQ(StreamIdMask(), structure_.promised_stream_id);
272 }
273 }
274 }
275
TEST_F(PushPromiseFieldsDecoderTest,DecodesRandomized)276 TEST_F(PushPromiseFieldsDecoderTest, DecodesRandomized) {
277 TestDecodingRandomizedStructures();
278 }
279
280 //------------------------------------------------------------------------------
281
282 class PingFieldsDecoderTest : public StructureDecoderTest<Http2PingFields> {};
283
TEST_F(PingFieldsDecoderTest,DecodesLiteral)284 TEST_F(PingFieldsDecoderTest, DecodesLiteral) {
285 {
286 // Each byte is different, so can detect if order changed.
287 const char kData[] = {
288 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
289 };
290 DecodeLeadingStructure(kData);
291 if (!HasFailure()) {
292 EXPECT_EQ(absl::string_view(kData, 8),
293 ToStringPiece(structure_.opaque_bytes));
294 }
295 }
296 {
297 // All zeros, detect problems handling NULs.
298 const char kData[] = {
299 '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
300 };
301 DecodeLeadingStructure(kData);
302 if (!HasFailure()) {
303 EXPECT_EQ(absl::string_view(kData, 8),
304 ToStringPiece(structure_.opaque_bytes));
305 }
306 }
307 {
308 const char kData[] = {
309 '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
310 };
311 DecodeLeadingStructure(kData);
312 if (!HasFailure()) {
313 EXPECT_EQ(absl::string_view(kData, 8),
314 ToStringPiece(structure_.opaque_bytes));
315 }
316 }
317 }
318
TEST_F(PingFieldsDecoderTest,DecodesRandomized)319 TEST_F(PingFieldsDecoderTest, DecodesRandomized) {
320 TestDecodingRandomizedStructures();
321 }
322
323 //------------------------------------------------------------------------------
324
325 class GoAwayFieldsDecoderTest : public StructureDecoderTest<Http2GoAwayFields> {
326 };
327
TEST_F(GoAwayFieldsDecoderTest,DecodesLiteral)328 TEST_F(GoAwayFieldsDecoderTest, DecodesLiteral) {
329 {
330 const char kData[] = {
331 '\x00', '\x00', '\x00', '\x00', // Last Stream ID: 0
332 '\x00', '\x00', '\x00', '\x00', // Error: NO_ERROR (0)
333 };
334 DecodeLeadingStructure(kData);
335 if (!HasFailure()) {
336 EXPECT_EQ(0u, structure_.last_stream_id);
337 EXPECT_TRUE(structure_.IsSupportedErrorCode());
338 EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_.error_code);
339 }
340 }
341 {
342 const char kData[] = {
343 '\x00', '\x00', '\x00', '\x01', // Last Stream ID: 1
344 '\x00', '\x00', '\x00', '\x0d', // Error: HTTP_1_1_REQUIRED
345 };
346 DecodeLeadingStructure(kData);
347 if (!HasFailure()) {
348 EXPECT_EQ(1u, structure_.last_stream_id);
349 EXPECT_TRUE(structure_.IsSupportedErrorCode());
350 EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_.error_code);
351 }
352 }
353 {
354 const char kData[] = {
355 '\xff', '\xff',
356 '\xff', '\xff', // Last Stream ID: max uint31 and R-bit
357 '\xff', '\xff',
358 '\xff', '\xff', // Error: max uint32 (Unknown error code)
359 };
360 DecodeLeadingStructure(kData);
361 if (!HasFailure()) {
362 EXPECT_EQ(StreamIdMask(), structure_.last_stream_id); // No high-bit.
363 EXPECT_FALSE(structure_.IsSupportedErrorCode());
364 EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code);
365 }
366 }
367 }
368
TEST_F(GoAwayFieldsDecoderTest,DecodesRandomized)369 TEST_F(GoAwayFieldsDecoderTest, DecodesRandomized) {
370 TestDecodingRandomizedStructures();
371 }
372
373 //------------------------------------------------------------------------------
374
375 class WindowUpdateFieldsDecoderTest
376 : public StructureDecoderTest<Http2WindowUpdateFields> {};
377
TEST_F(WindowUpdateFieldsDecoderTest,DecodesLiteral)378 TEST_F(WindowUpdateFieldsDecoderTest, DecodesLiteral) {
379 {
380 const char kData[] = {
381 '\x00', '\x01', '\x00', '\x00', // Window Size Increment: 2 ^ 16
382 };
383 DecodeLeadingStructure(kData);
384 if (!HasFailure()) {
385 EXPECT_EQ(1u << 16, structure_.window_size_increment);
386 }
387 }
388 {
389 // Increment must be non-zero, but we need to be able to decode the invalid
390 // zero to detect it.
391 const char kData[] = {
392 '\x00', '\x00', '\x00', '\x00', // Window Size Increment: 0
393 };
394 DecodeLeadingStructure(kData);
395 if (!HasFailure()) {
396 EXPECT_EQ(0u, structure_.window_size_increment);
397 }
398 }
399 {
400 // Increment has R-bit (reserved for future use) set, which
401 // should be cleared by the decoder.
402 // clang-format off
403 const char kData[] = {
404 // Window Size Increment: max uint31 and R-bit
405 '\xff', '\xff', '\xff', '\xff',
406 };
407 // clang-format on
408 DecodeLeadingStructure(kData);
409 if (!HasFailure()) {
410 EXPECT_EQ(StreamIdMask(), structure_.window_size_increment);
411 }
412 }
413 }
414
TEST_F(WindowUpdateFieldsDecoderTest,DecodesRandomized)415 TEST_F(WindowUpdateFieldsDecoderTest, DecodesRandomized) {
416 TestDecodingRandomizedStructures();
417 }
418
419 //------------------------------------------------------------------------------
420
421 class AltSvcFieldsDecoderTest : public StructureDecoderTest<Http2AltSvcFields> {
422 };
423
TEST_F(AltSvcFieldsDecoderTest,DecodesLiteral)424 TEST_F(AltSvcFieldsDecoderTest, DecodesLiteral) {
425 {
426 const char kData[] = {
427 '\x00', '\x00', // Origin Length: 0
428 };
429 DecodeLeadingStructure(kData);
430 if (!HasFailure()) {
431 EXPECT_EQ(0, structure_.origin_length);
432 }
433 }
434 {
435 const char kData[] = {
436 '\x00', '\x14', // Origin Length: 20
437 };
438 DecodeLeadingStructure(kData);
439 if (!HasFailure()) {
440 EXPECT_EQ(20, structure_.origin_length);
441 }
442 }
443 {
444 const char kData[] = {
445 '\xff', '\xff', // Origin Length: uint16 max
446 };
447 DecodeLeadingStructure(kData);
448 if (!HasFailure()) {
449 EXPECT_EQ(65535, structure_.origin_length);
450 }
451 }
452 }
453
TEST_F(AltSvcFieldsDecoderTest,DecodesRandomized)454 TEST_F(AltSvcFieldsDecoderTest, DecodesRandomized) {
455 TestDecodingRandomizedStructures();
456 }
457
458 } // namespace
459 } // namespace test
460 } // namespace http2
461