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