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/http2_frame_decoder.h"
6
7 // Tests of Http2FrameDecoder.
8
9 #include <string>
10 #include <vector>
11
12 #include "absl/strings/string_view.h"
13 #include "quiche/http2/http2_constants.h"
14 #include "quiche/http2/test_tools/frame_parts.h"
15 #include "quiche/http2/test_tools/frame_parts_collector_listener.h"
16 #include "quiche/http2/test_tools/http2_random.h"
17 #include "quiche/http2/test_tools/random_decoder_test_base.h"
18 #include "quiche/http2/test_tools/verify_macros.h"
19 #include "quiche/common/platform/api/quiche_logging.h"
20
21 using ::testing::AssertionSuccess;
22
23 namespace http2 {
24 namespace test {
25 class Http2FrameDecoderPeer {
26 public:
remaining_total_payload(Http2FrameDecoder * decoder)27 static size_t remaining_total_payload(Http2FrameDecoder* decoder) {
28 return decoder->frame_decoder_state_.remaining_total_payload();
29 }
30 };
31
32 namespace {
33
34 class Http2FrameDecoderTest : public RandomDecoderTest {
35 protected:
StartDecoding(DecodeBuffer * db)36 DecodeStatus StartDecoding(DecodeBuffer* db) override {
37 QUICHE_DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining();
38 collector_.Reset();
39 PrepareDecoder();
40
41 DecodeStatus status = decoder_->DecodeFrame(db);
42 if (status != DecodeStatus::kDecodeInProgress) {
43 // Keep track of this so that a concrete test can verify that both fast
44 // and slow decoding paths have been tested.
45 ++fast_decode_count_;
46 if (status == DecodeStatus::kDecodeError) {
47 ConfirmDiscardsRemainingPayload();
48 }
49 }
50 return status;
51 }
52
ResumeDecoding(DecodeBuffer * db)53 DecodeStatus ResumeDecoding(DecodeBuffer* db) override {
54 QUICHE_DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining();
55 DecodeStatus status = decoder_->DecodeFrame(db);
56 if (status != DecodeStatus::kDecodeInProgress) {
57 // Keep track of this so that a concrete test can verify that both fast
58 // and slow decoding paths have been tested.
59 ++slow_decode_count_;
60 if (status == DecodeStatus::kDecodeError) {
61 ConfirmDiscardsRemainingPayload();
62 }
63 }
64 return status;
65 }
66
67 // When an error is returned, the decoder is in state kDiscardPayload, and
68 // stays there until the remaining bytes of the frame's payload have been
69 // skipped over. There are no callbacks for this situation.
ConfirmDiscardsRemainingPayload()70 void ConfirmDiscardsRemainingPayload() {
71 ASSERT_TRUE(decoder_->IsDiscardingPayload());
72 size_t remaining =
73 Http2FrameDecoderPeer::remaining_total_payload(decoder_.get());
74 // The decoder will discard the remaining bytes, but not go beyond that,
75 // which these conditions verify.
76 size_t extra = 10;
77 std::string junk(remaining + extra, '0');
78 DecodeBuffer tmp(junk);
79 EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_->DecodeFrame(&tmp));
80 EXPECT_EQ(remaining, tmp.Offset());
81 EXPECT_EQ(extra, tmp.Remaining());
82 EXPECT_FALSE(decoder_->IsDiscardingPayload());
83 }
84
PrepareDecoder()85 void PrepareDecoder() {
86 decoder_ = std::make_unique<Http2FrameDecoder>(&collector_);
87 decoder_->set_maximum_payload_size(maximum_payload_size_);
88 }
89
ResetDecodeSpeedCounters()90 void ResetDecodeSpeedCounters() {
91 fast_decode_count_ = 0;
92 slow_decode_count_ = 0;
93 }
94
VerifyCollected(const FrameParts & expected)95 AssertionResult VerifyCollected(const FrameParts& expected) {
96 HTTP2_VERIFY_FALSE(collector_.IsInProgress());
97 HTTP2_VERIFY_EQ(1u, collector_.size());
98 return expected.VerifyEquals(*collector_.frame(0));
99 }
100
DecodePayloadAndValidateSeveralWays(absl::string_view payload,Validator validator)101 AssertionResult DecodePayloadAndValidateSeveralWays(absl::string_view payload,
102 Validator validator) {
103 DecodeBuffer db(payload);
104 bool start_decoding_requires_non_empty = false;
105 return DecodeAndValidateSeveralWays(&db, start_decoding_requires_non_empty,
106 validator);
107 }
108
109 // Decode one frame's payload and confirm that the listener recorded the
110 // expected FrameParts instance, and only one FrameParts instance. The
111 // payload will be decoded several times with different partitionings
112 // of the payload, and after each the validator will be called.
DecodePayloadAndValidateSeveralWays(absl::string_view payload,const FrameParts & expected)113 AssertionResult DecodePayloadAndValidateSeveralWays(
114 absl::string_view payload, const FrameParts& expected) {
115 auto validator = [&expected, this](const DecodeBuffer& /*input*/,
116 DecodeStatus status) -> AssertionResult {
117 HTTP2_VERIFY_EQ(status, DecodeStatus::kDecodeDone);
118 return VerifyCollected(expected);
119 };
120 ResetDecodeSpeedCounters();
121 HTTP2_VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
122 payload, ValidateDoneAndEmpty(validator)));
123 HTTP2_VERIFY_GT(fast_decode_count_, 0u);
124 HTTP2_VERIFY_GT(slow_decode_count_, 0u);
125
126 // Repeat with more input; it should stop without reading that input.
127 std::string next_frame = Random().RandString(10);
128 std::string input(payload.data(), payload.size());
129 input += next_frame;
130
131 ResetDecodeSpeedCounters();
132 HTTP2_VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
133 payload, ValidateDoneAndOffset(payload.size(), validator)));
134 HTTP2_VERIFY_GT(fast_decode_count_, 0u);
135 HTTP2_VERIFY_GT(slow_decode_count_, 0u);
136
137 return AssertionSuccess();
138 }
139
140 template <size_t N>
DecodePayloadAndValidateSeveralWays(const char (& buf)[N],const FrameParts & expected)141 AssertionResult DecodePayloadAndValidateSeveralWays(
142 const char (&buf)[N], const FrameParts& expected) {
143 return DecodePayloadAndValidateSeveralWays(absl::string_view(buf, N),
144 expected);
145 }
146
147 template <size_t N>
DecodePayloadAndValidateSeveralWays(const char (& buf)[N],const Http2FrameHeader & header)148 AssertionResult DecodePayloadAndValidateSeveralWays(
149 const char (&buf)[N], const Http2FrameHeader& header) {
150 return DecodePayloadAndValidateSeveralWays(absl::string_view(buf, N),
151 FrameParts(header));
152 }
153
154 template <size_t N>
DecodePayloadExpectingError(const char (& buf)[N],const FrameParts & expected)155 AssertionResult DecodePayloadExpectingError(const char (&buf)[N],
156 const FrameParts& expected) {
157 auto validator = [&expected, this](const DecodeBuffer& /*input*/,
158 DecodeStatus status) -> AssertionResult {
159 HTTP2_VERIFY_EQ(status, DecodeStatus::kDecodeError);
160 return VerifyCollected(expected);
161 };
162 ResetDecodeSpeedCounters();
163 EXPECT_TRUE(
164 DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator));
165 EXPECT_GT(fast_decode_count_, 0u);
166 EXPECT_GT(slow_decode_count_, 0u);
167 return AssertionSuccess();
168 }
169
170 template <size_t N>
DecodePayloadExpectingFrameSizeError(const char (& buf)[N],FrameParts expected)171 AssertionResult DecodePayloadExpectingFrameSizeError(const char (&buf)[N],
172 FrameParts expected) {
173 expected.SetHasFrameSizeError(true);
174 return DecodePayloadExpectingError(buf, expected);
175 }
176
177 template <size_t N>
DecodePayloadExpectingFrameSizeError(const char (& buf)[N],const Http2FrameHeader & header)178 AssertionResult DecodePayloadExpectingFrameSizeError(
179 const char (&buf)[N], const Http2FrameHeader& header) {
180 return DecodePayloadExpectingFrameSizeError(buf, FrameParts(header));
181 }
182
183 // Count of payloads that are fully decoded by StartDecodingPayload or for
184 // which an error was detected by StartDecodingPayload.
185 size_t fast_decode_count_ = 0;
186
187 // Count of payloads that required calling ResumeDecodingPayload in order to
188 // decode completely, or for which an error was detected by
189 // ResumeDecodingPayload.
190 size_t slow_decode_count_ = 0;
191
192 uint32_t maximum_payload_size_ = Http2SettingsInfo::DefaultMaxFrameSize();
193 FramePartsCollectorListener collector_;
194 std::unique_ptr<Http2FrameDecoder> decoder_;
195 };
196
197 ////////////////////////////////////////////////////////////////////////////////
198 // Tests that pass the minimum allowed size for the frame type, which is often
199 // empty. The tests are in order by frame type value (i.e. 0 for DATA frames).
200
TEST_F(Http2FrameDecoderTest,DataEmpty)201 TEST_F(Http2FrameDecoderTest, DataEmpty) {
202 const char kFrameData[] = {
203 '\x00', '\x00', '\x00', // Payload length: 0
204 '\x00', // DATA
205 '\x00', // Flags: none
206 '\x00', '\x00', '\x00',
207 '\x00', // Stream ID: 0 (invalid but unchecked here)
208 };
209 Http2FrameHeader header(0, Http2FrameType::DATA, 0, 0);
210 FrameParts expected(header, "");
211 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
212 }
213
TEST_F(Http2FrameDecoderTest,HeadersEmpty)214 TEST_F(Http2FrameDecoderTest, HeadersEmpty) {
215 const char kFrameData[] = {
216 '\x00', '\x00', '\x00', // Payload length: 0
217 '\x01', // HEADERS
218 '\x00', // Flags: none
219 '\x00', '\x00', '\x00', '\x01', // Stream ID: 0 (REQUIRES ID)
220 };
221 Http2FrameHeader header(0, Http2FrameType::HEADERS, 0, 1);
222 FrameParts expected(header, "");
223 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
224 }
225
TEST_F(Http2FrameDecoderTest,Priority)226 TEST_F(Http2FrameDecoderTest, Priority) {
227 const char kFrameData[] = {
228 '\x00', '\x00', '\x05', // Length: 5
229 '\x02', // Type: PRIORITY
230 '\x00', // Flags: none
231 '\x00', '\x00', '\x00', '\x02', // Stream: 2
232 '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive)
233 '\x10', // Weight: 17
234 };
235 Http2FrameHeader header(5, Http2FrameType::PRIORITY, 0, 2);
236 FrameParts expected(header);
237 expected.SetOptPriority(Http2PriorityFields(1, 17, true));
238 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
239 }
240
TEST_F(Http2FrameDecoderTest,RstStream)241 TEST_F(Http2FrameDecoderTest, RstStream) {
242 const char kFrameData[] = {
243 '\x00', '\x00', '\x04', // Length: 4
244 '\x03', // Type: RST_STREAM
245 '\x00', // Flags: none
246 '\x00', '\x00', '\x00', '\x01', // Stream: 1
247 '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR
248 };
249 Http2FrameHeader header(4, Http2FrameType::RST_STREAM, 0, 1);
250 FrameParts expected(header);
251 expected.SetOptRstStreamErrorCode(Http2ErrorCode::PROTOCOL_ERROR);
252 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
253 }
254
TEST_F(Http2FrameDecoderTest,SettingsEmpty)255 TEST_F(Http2FrameDecoderTest, SettingsEmpty) {
256 const char kFrameData[] = {
257 '\x00', '\x00', '\x00', // Length: 0
258 '\x04', // Type: SETTINGS
259 '\x00', // Flags: none
260 '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here)
261 };
262 Http2FrameHeader header(0, Http2FrameType::SETTINGS, 0, 1);
263 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, header));
264 }
265
TEST_F(Http2FrameDecoderTest,SettingsAck)266 TEST_F(Http2FrameDecoderTest, SettingsAck) {
267 const char kFrameData[] = {
268 '\x00', '\x00', '\x00', // Length: 6
269 '\x04', // Type: SETTINGS
270 '\x01', // Flags: ACK
271 '\x00', '\x00', '\x00', '\x00', // Stream: 0
272 };
273 Http2FrameHeader header(0, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0);
274 FrameParts expected(header);
275 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
276 }
277
TEST_F(Http2FrameDecoderTest,PushPromiseMinimal)278 TEST_F(Http2FrameDecoderTest, PushPromiseMinimal) {
279 const char kFrameData[] = {
280 '\x00', '\x00', '\x04', // Payload length: 4
281 '\x05', // PUSH_PROMISE
282 '\x04', // Flags: END_HEADERS
283 '\x00', '\x00', '\x00',
284 '\x02', // Stream: 2 (invalid but unchecked here)
285 '\x00', '\x00', '\x00',
286 '\x01', // Promised: 1 (invalid but unchecked here)
287 };
288 Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE,
289 Http2FrameFlag::END_HEADERS, 2);
290 FrameParts expected(header, "");
291 expected.SetOptPushPromise(Http2PushPromiseFields{1});
292 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
293 }
294
TEST_F(Http2FrameDecoderTest,Ping)295 TEST_F(Http2FrameDecoderTest, Ping) {
296 const char kFrameData[] = {
297 '\x00', '\x00', '\x08', // Length: 8
298 '\x06', // Type: PING
299 '\xfe', // Flags: no valid flags
300 '\x00', '\x00', '\x00', '\x00', // Stream: 0
301 's', 'o', 'm', 'e', // "some"
302 'd', 'a', 't', 'a', // "data"
303 };
304 Http2FrameHeader header(8, Http2FrameType::PING, 0, 0);
305 FrameParts expected(header);
306 expected.SetOptPing(
307 Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}});
308 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
309 }
310
TEST_F(Http2FrameDecoderTest,PingAck)311 TEST_F(Http2FrameDecoderTest, PingAck) {
312 const char kFrameData[] = {
313 '\x00', '\x00', '\x08', // Length: 8
314 '\x06', // Type: PING
315 '\xff', // Flags: ACK (plus all invalid flags)
316 '\x00', '\x00', '\x00', '\x00', // Stream: 0
317 's', 'o', 'm', 'e', // "some"
318 'd', 'a', 't', 'a', // "data"
319 };
320 Http2FrameHeader header(8, Http2FrameType::PING, Http2FrameFlag::ACK, 0);
321 FrameParts expected(header);
322 expected.SetOptPing(
323 Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}});
324 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
325 }
326
TEST_F(Http2FrameDecoderTest,GoAwayMinimal)327 TEST_F(Http2FrameDecoderTest, GoAwayMinimal) {
328 const char kFrameData[] = {
329 '\x00', '\x00', '\x08', // Length: 8 (no opaque data)
330 '\x07', // Type: GOAWAY
331 '\xff', // Flags: 0xff (no valid flags)
332 '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here)
333 '\x80', '\x00', '\x00', '\xff', // Last: 255 (plus R bit)
334 '\x00', '\x00', '\x00', '\x09', // Error: COMPRESSION_ERROR
335 };
336 Http2FrameHeader header(8, Http2FrameType::GOAWAY, 0, 1);
337 FrameParts expected(header);
338 expected.SetOptGoaway(
339 Http2GoAwayFields(255, Http2ErrorCode::COMPRESSION_ERROR));
340 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
341 }
342
TEST_F(Http2FrameDecoderTest,WindowUpdate)343 TEST_F(Http2FrameDecoderTest, WindowUpdate) {
344 const char kFrameData[] = {
345 '\x00', '\x00', '\x04', // Length: 4
346 '\x08', // Type: WINDOW_UPDATE
347 '\x0f', // Flags: 0xff (no valid flags)
348 '\x00', '\x00', '\x00', '\x01', // Stream: 1
349 '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit)
350 };
351 Http2FrameHeader header(4, Http2FrameType::WINDOW_UPDATE, 0, 1);
352 FrameParts expected(header);
353 expected.SetOptWindowUpdateIncrement(1024);
354 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
355 }
356
TEST_F(Http2FrameDecoderTest,ContinuationEmpty)357 TEST_F(Http2FrameDecoderTest, ContinuationEmpty) {
358 const char kFrameData[] = {
359 '\x00', '\x00', '\x00', // Payload length: 0
360 '\x09', // CONTINUATION
361 '\x00', // Flags: none
362 '\x00', '\x00', '\x00',
363 '\x00', // Stream ID: 0 (invalid but unchecked here)
364 };
365 Http2FrameHeader header(0, Http2FrameType::CONTINUATION, 0, 0);
366 FrameParts expected(header);
367 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
368 }
369
TEST_F(Http2FrameDecoderTest,AltSvcMinimal)370 TEST_F(Http2FrameDecoderTest, AltSvcMinimal) {
371 const char kFrameData[] = {
372 '\x00', '\x00', '\x02', // Payload length: 2
373 '\x0a', // ALTSVC
374 '\xff', // Flags: none (plus 0xff)
375 '\x00', '\x00', '\x00',
376 '\x00', // Stream ID: 0 (invalid but unchecked here)
377 '\x00', '\x00', // Origin Length: 0
378 };
379 Http2FrameHeader header(2, Http2FrameType::ALTSVC, 0, 0);
380 FrameParts expected(header);
381 expected.SetOptAltsvcOriginLength(0);
382 expected.SetOptAltsvcValueLength(0);
383 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
384 }
385
TEST_F(Http2FrameDecoderTest,UnknownEmpty)386 TEST_F(Http2FrameDecoderTest, UnknownEmpty) {
387 const char kFrameData[] = {
388 '\x00', '\x00', '\x00', // Payload length: 0
389 '\x20', // 32 (unknown)
390 '\xff', // Flags: all
391 '\x00', '\x00', '\x00', '\x00', // Stream ID: 0
392 };
393 Http2FrameHeader header(0, static_cast<Http2FrameType>(32), 0xff, 0);
394 FrameParts expected(header);
395 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
396 }
397
398 ////////////////////////////////////////////////////////////////////////////////
399 // Tests of longer payloads, for those frame types that allow longer payloads.
400
TEST_F(Http2FrameDecoderTest,DataPayload)401 TEST_F(Http2FrameDecoderTest, DataPayload) {
402 const char kFrameData[] = {
403 '\x00', '\x00', '\x03', // Payload length: 7
404 '\x00', // DATA
405 '\x80', // Flags: 0x80
406 '\x00', '\x00', '\x02', '\x02', // Stream ID: 514
407 'a', 'b', 'c', // Data
408 };
409 Http2FrameHeader header(3, Http2FrameType::DATA, 0, 514);
410 FrameParts expected(header, "abc");
411 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
412 }
413
TEST_F(Http2FrameDecoderTest,HeadersPayload)414 TEST_F(Http2FrameDecoderTest, HeadersPayload) {
415 const char kFrameData[] = {
416 '\x00', '\x00', '\x03', // Payload length: 3
417 '\x01', // HEADERS
418 '\x05', // Flags: END_STREAM | END_HEADERS
419 '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID)
420 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
421 };
422 Http2FrameHeader header(
423 3, Http2FrameType::HEADERS,
424 Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS, 2);
425 FrameParts expected(header, "abc");
426 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
427 }
428
TEST_F(Http2FrameDecoderTest,HeadersPriority)429 TEST_F(Http2FrameDecoderTest, HeadersPriority) {
430 const char kFrameData[] = {
431 '\x00', '\x00', '\x05', // Payload length: 5
432 '\x01', // HEADERS
433 '\x20', // Flags: PRIORITY
434 '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID)
435 '\x00', '\x00', '\x00', '\x01', // Parent: 1 (Not Exclusive)
436 '\xff', // Weight: 256
437 };
438 Http2FrameHeader header(5, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY,
439 2);
440 FrameParts expected(header);
441 expected.SetOptPriority(Http2PriorityFields(1, 256, false));
442 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
443 }
444
TEST_F(Http2FrameDecoderTest,Settings)445 TEST_F(Http2FrameDecoderTest, Settings) {
446 const char kFrameData[] = {
447 '\x00', '\x00', '\x0c', // Length: 12
448 '\x04', // Type: SETTINGS
449 '\x00', // Flags: none
450 '\x00', '\x00', '\x00', '\x00', // Stream: 0
451 '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE
452 '\x0a', '\x0b', '\x0c', '\x0d', // Value: 168496141
453 '\x00', '\x02', // Param: ENABLE_PUSH
454 '\x00', '\x00', '\x00', '\x03', // Value: 3 (invalid but unchecked here)
455 };
456 Http2FrameHeader header(12, Http2FrameType::SETTINGS, 0, 0);
457 FrameParts expected(header);
458 expected.AppendSetting(Http2SettingFields(
459 Http2SettingsParameter::INITIAL_WINDOW_SIZE, 168496141));
460 expected.AppendSetting(
461 Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3));
462 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
463 }
464
TEST_F(Http2FrameDecoderTest,PushPromisePayload)465 TEST_F(Http2FrameDecoderTest, PushPromisePayload) {
466 const char kFrameData[] = {
467 '\x00', '\x00', 7, // Payload length: 7
468 '\x05', // PUSH_PROMISE
469 '\x04', // Flags: END_HEADERS
470 '\x00', '\x00', '\x00', '\xff', // Stream ID: 255
471 '\x00', '\x00', '\x01', '\x00', // Promised: 256
472 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
473 };
474 Http2FrameHeader header(7, Http2FrameType::PUSH_PROMISE,
475 Http2FrameFlag::END_HEADERS, 255);
476 FrameParts expected(header, "abc");
477 expected.SetOptPushPromise(Http2PushPromiseFields{256});
478 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
479 }
480
TEST_F(Http2FrameDecoderTest,GoAwayOpaqueData)481 TEST_F(Http2FrameDecoderTest, GoAwayOpaqueData) {
482 const char kFrameData[] = {
483 '\x00', '\x00', '\x0e', // Length: 14
484 '\x07', // Type: GOAWAY
485 '\xff', // Flags: 0xff (no valid flags)
486 '\x80', '\x00', '\x00', '\x00', // Stream: 0 (plus R bit)
487 '\x00', '\x00', '\x01', '\x00', // Last: 256
488 '\x00', '\x00', '\x00', '\x03', // Error: FLOW_CONTROL_ERROR
489 'o', 'p', 'a', 'q', 'u', 'e',
490 };
491 Http2FrameHeader header(14, Http2FrameType::GOAWAY, 0, 0);
492 FrameParts expected(header, "opaque");
493 expected.SetOptGoaway(
494 Http2GoAwayFields(256, Http2ErrorCode::FLOW_CONTROL_ERROR));
495 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
496 }
497
TEST_F(Http2FrameDecoderTest,ContinuationPayload)498 TEST_F(Http2FrameDecoderTest, ContinuationPayload) {
499 const char kFrameData[] = {
500 '\x00', '\x00', '\x03', // Payload length: 3
501 '\x09', // CONTINUATION
502 '\xff', // Flags: END_HEADERS | 0xfb
503 '\x00', '\x00', '\x00', '\x02', // Stream ID: 2
504 'a', 'b', 'c', // Data
505 };
506 Http2FrameHeader header(3, Http2FrameType::CONTINUATION,
507 Http2FrameFlag::END_HEADERS, 2);
508 FrameParts expected(header, "abc");
509 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
510 }
511
TEST_F(Http2FrameDecoderTest,AltSvcPayload)512 TEST_F(Http2FrameDecoderTest, AltSvcPayload) {
513 const char kFrameData[] = {
514 '\x00', '\x00', '\x08', // Payload length: 3
515 '\x0a', // ALTSVC
516 '\x00', // Flags: none
517 '\x00', '\x00', '\x00', '\x02', // Stream ID: 2
518 '\x00', '\x03', // Origin Length: 0
519 'a', 'b', 'c', // Origin
520 'd', 'e', 'f', // Value
521 };
522 Http2FrameHeader header(8, Http2FrameType::ALTSVC, 0, 2);
523 FrameParts expected(header);
524 expected.SetAltSvcExpected("abc", "def");
525 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
526 }
527
TEST_F(Http2FrameDecoderTest,PriorityUpdatePayload)528 TEST_F(Http2FrameDecoderTest, PriorityUpdatePayload) {
529 const char kFrameData[] = {
530 '\x00', '\x00', '\x07', // Payload length: 7
531 '\x10', // PRIORITY_UPDATE
532 '\x00', // Flags: none
533 '\x00', '\x00', '\x00', '\x00', // Stream ID: 0
534 '\x00', '\x00', '\x00', '\x05', // Prioritized Stream ID: 5
535 'a', 'b', 'c', // Priority Field Value
536 };
537 Http2FrameHeader header(7, Http2FrameType::PRIORITY_UPDATE, 0, 0);
538
539 FrameParts expected(header, "abc");
540 expected.SetOptPriorityUpdate(Http2PriorityUpdateFields{5});
541 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
542 }
543
TEST_F(Http2FrameDecoderTest,UnknownPayload)544 TEST_F(Http2FrameDecoderTest, UnknownPayload) {
545 const char kFrameData[] = {
546 '\x00', '\x00', '\x03', // Payload length: 3
547 '\x30', // 48 (unknown)
548 '\x00', // Flags: none
549 '\x00', '\x00', '\x00', '\x02', // Stream ID: 2
550 'a', 'b', 'c', // Payload
551 };
552 Http2FrameHeader header(3, static_cast<Http2FrameType>(48), 0, 2);
553 FrameParts expected(header, "abc");
554 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
555 }
556
557 ////////////////////////////////////////////////////////////////////////////////
558 // Tests of padded payloads, for those frame types that allow padding.
559
TEST_F(Http2FrameDecoderTest,DataPayloadAndPadding)560 TEST_F(Http2FrameDecoderTest, DataPayloadAndPadding) {
561 const char kFrameData[] = {
562 '\x00', '\x00', '\x07', // Payload length: 7
563 '\x00', // DATA
564 '\x09', // Flags: END_STREAM | PADDED
565 '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID)
566 '\x03', // Pad Len
567 'a', 'b', 'c', // Data
568 '\x00', '\x00', '\x00', // Padding
569 };
570 Http2FrameHeader header(7, Http2FrameType::DATA,
571 Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED,
572 2);
573 size_t total_pad_length = 4; // Including the Pad Length field.
574 FrameParts expected(header, "abc", total_pad_length);
575 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
576 }
577
TEST_F(Http2FrameDecoderTest,HeadersPayloadAndPadding)578 TEST_F(Http2FrameDecoderTest, HeadersPayloadAndPadding) {
579 const char kFrameData[] = {
580 '\x00', '\x00', '\x07', // Payload length: 7
581 '\x01', // HEADERS
582 '\x08', // Flags: PADDED
583 '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID)
584 '\x03', // Pad Len
585 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
586 '\x00', '\x00', '\x00', // Padding
587 };
588 Http2FrameHeader header(7, Http2FrameType::HEADERS, Http2FrameFlag::PADDED,
589 2);
590 size_t total_pad_length = 4; // Including the Pad Length field.
591 FrameParts expected(header, "abc", total_pad_length);
592 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
593 }
594
TEST_F(Http2FrameDecoderTest,HeadersPayloadPriorityAndPadding)595 TEST_F(Http2FrameDecoderTest, HeadersPayloadPriorityAndPadding) {
596 const char kFrameData[] = {
597 '\x00', '\x00', '\x0c', // Payload length: 12
598 '\x01', // HEADERS
599 '\xff', // Flags: all, including undefined
600 '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID)
601 '\x03', // Pad Len
602 '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive)
603 '\x10', // Weight: 17
604 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
605 '\x00', '\x00', '\x00', // Padding
606 };
607 Http2FrameHeader header(12, Http2FrameType::HEADERS,
608 Http2FrameFlag::END_STREAM |
609 Http2FrameFlag::END_HEADERS |
610 Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY,
611 2);
612 size_t total_pad_length = 4; // Including the Pad Length field.
613 FrameParts expected(header, "abc", total_pad_length);
614 expected.SetOptPriority(Http2PriorityFields(1, 17, true));
615 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
616 }
617
TEST_F(Http2FrameDecoderTest,PushPromisePayloadAndPadding)618 TEST_F(Http2FrameDecoderTest, PushPromisePayloadAndPadding) {
619 const char kFrameData[] = {
620 '\x00', '\x00', 11, // Payload length: 11
621 '\x05', // PUSH_PROMISE
622 '\xff', // Flags: END_HEADERS | PADDED | 0xf3
623 '\x00', '\x00', '\x00', '\x01', // Stream ID: 1
624 '\x03', // Pad Len
625 '\x00', '\x00', '\x00', '\x02', // Promised: 2
626 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid)
627 '\x00', '\x00', '\x00', // Padding
628 };
629 Http2FrameHeader header(11, Http2FrameType::PUSH_PROMISE,
630 Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED,
631 1);
632 size_t total_pad_length = 4; // Including the Pad Length field.
633 FrameParts expected(header, "abc", total_pad_length);
634 expected.SetOptPushPromise(Http2PushPromiseFields{2});
635 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
636 }
637
638 ////////////////////////////////////////////////////////////////////////////////
639 // Payload too short errors.
640
TEST_F(Http2FrameDecoderTest,DataMissingPadLengthField)641 TEST_F(Http2FrameDecoderTest, DataMissingPadLengthField) {
642 const char kFrameData[] = {
643 '\x00', '\x00', '\x00', // Payload length: 0
644 '\x00', // DATA
645 '\x08', // Flags: PADDED
646 '\x00', '\x00', '\x00', '\x01', // Stream ID: 1
647 };
648 Http2FrameHeader header(0, Http2FrameType::DATA, Http2FrameFlag::PADDED, 1);
649 FrameParts expected(header);
650 expected.SetOptMissingLength(1);
651 EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected));
652 }
653
TEST_F(Http2FrameDecoderTest,HeaderPaddingTooLong)654 TEST_F(Http2FrameDecoderTest, HeaderPaddingTooLong) {
655 const char kFrameData[] = {
656 '\x00', '\x00', '\x02', // Payload length: 0
657 '\x01', // HEADERS
658 '\x08', // Flags: PADDED
659 '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536
660 '\xff', // Pad Len: 255
661 '\x00', // Only one byte of padding
662 };
663 Http2FrameHeader header(2, Http2FrameType::HEADERS, Http2FrameFlag::PADDED,
664 65536);
665 FrameParts expected(header);
666 expected.SetOptMissingLength(254);
667 EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected));
668 }
669
TEST_F(Http2FrameDecoderTest,HeaderMissingPriority)670 TEST_F(Http2FrameDecoderTest, HeaderMissingPriority) {
671 const char kFrameData[] = {
672 '\x00', '\x00', '\x04', // Payload length: 0
673 '\x01', // HEADERS
674 '\x20', // Flags: PRIORITY
675 '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536
676 '\x00', '\x00', '\x00', '\x00', // Priority (truncated)
677 };
678 Http2FrameHeader header(4, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY,
679 65536);
680 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
681 }
682
TEST_F(Http2FrameDecoderTest,PriorityTooShort)683 TEST_F(Http2FrameDecoderTest, PriorityTooShort) {
684 const char kFrameData[] = {
685 '\x00', '\x00', '\x04', // Length: 5
686 '\x02', // Type: PRIORITY
687 '\x00', // Flags: none
688 '\x00', '\x00', '\x00', '\x02', // Stream: 2
689 '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive)
690 };
691 Http2FrameHeader header(4, Http2FrameType::PRIORITY, 0, 2);
692 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
693 }
694
TEST_F(Http2FrameDecoderTest,RstStreamTooShort)695 TEST_F(Http2FrameDecoderTest, RstStreamTooShort) {
696 const char kFrameData[] = {
697 '\x00', '\x00', '\x03', // Length: 4
698 '\x03', // Type: RST_STREAM
699 '\x00', // Flags: none
700 '\x00', '\x00', '\x00', '\x01', // Stream: 1
701 '\x00', '\x00', '\x00', // Truncated
702 };
703 Http2FrameHeader header(3, Http2FrameType::RST_STREAM, 0, 1);
704 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
705 }
706
707 // SETTINGS frames must a multiple of 6 bytes long, so an 9 byte payload is
708 // invalid.
TEST_F(Http2FrameDecoderTest,SettingsWrongSize)709 TEST_F(Http2FrameDecoderTest, SettingsWrongSize) {
710 const char kFrameData[] = {
711 '\x00', '\x00', '\x09', // Length: 2
712 '\x04', // Type: SETTINGS
713 '\x00', // Flags: none
714 '\x00', '\x00', '\x00', '\x00', // Stream: 0
715 '\x00', '\x02', // Param: ENABLE_PUSH
716 '\x00', '\x00', '\x00', '\x03', // Value: 1
717 '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE
718 '\x00', // Value: Truncated
719 };
720 Http2FrameHeader header(9, Http2FrameType::SETTINGS, 0, 0);
721 FrameParts expected(header);
722 expected.AppendSetting(
723 Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3));
724 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, expected));
725 }
726
TEST_F(Http2FrameDecoderTest,PushPromiseTooShort)727 TEST_F(Http2FrameDecoderTest, PushPromiseTooShort) {
728 const char kFrameData[] = {
729 '\x00', '\x00', 3, // Payload length: 3
730 '\x05', // PUSH_PROMISE
731 '\x00', // Flags: none
732 '\x00', '\x00', '\x00', '\x01', // Stream ID: 1
733 '\x00', '\x00', '\x00', // Truncated promise id
734 };
735 Http2FrameHeader header(3, Http2FrameType::PUSH_PROMISE, 0, 1);
736 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
737 }
738
TEST_F(Http2FrameDecoderTest,PushPromisePaddedTruncatedPromise)739 TEST_F(Http2FrameDecoderTest, PushPromisePaddedTruncatedPromise) {
740 const char kFrameData[] = {
741 '\x00', '\x00', 4, // Payload length: 4
742 '\x05', // PUSH_PROMISE
743 '\x08', // Flags: PADDED
744 '\x00', '\x00', '\x00', '\x01', // Stream ID: 1
745 '\x00', // Pad Len
746 '\x00', '\x00', '\x00', // Truncated promise id
747 };
748 Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE,
749 Http2FrameFlag::PADDED, 1);
750 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
751 }
752
TEST_F(Http2FrameDecoderTest,PingTooShort)753 TEST_F(Http2FrameDecoderTest, PingTooShort) {
754 const char kFrameData[] = {
755 '\x00', '\x00', '\x07', // Length: 8
756 '\x06', // Type: PING
757 '\xfe', // Flags: no valid flags
758 '\x00', '\x00', '\x00', '\x00', // Stream: 0
759 's', 'o', 'm', 'e', // "some"
760 'd', 'a', 't', // Too little
761 };
762 Http2FrameHeader header(7, Http2FrameType::PING, 0, 0);
763 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
764 }
765
TEST_F(Http2FrameDecoderTest,GoAwayTooShort)766 TEST_F(Http2FrameDecoderTest, GoAwayTooShort) {
767 const char kFrameData[] = {
768 '\x00', '\x00', '\x00', // Length: 0
769 '\x07', // Type: GOAWAY
770 '\xff', // Flags: 0xff (no valid flags)
771 '\x00', '\x00', '\x00', '\x00', // Stream: 0
772 };
773 Http2FrameHeader header(0, Http2FrameType::GOAWAY, 0, 0);
774 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
775 }
776
TEST_F(Http2FrameDecoderTest,WindowUpdateTooShort)777 TEST_F(Http2FrameDecoderTest, WindowUpdateTooShort) {
778 const char kFrameData[] = {
779 '\x00', '\x00', '\x03', // Length: 3
780 '\x08', // Type: WINDOW_UPDATE
781 '\x0f', // Flags: 0xff (no valid flags)
782 '\x00', '\x00', '\x00', '\x01', // Stream: 1
783 '\x80', '\x00', '\x04', // Truncated
784 };
785 Http2FrameHeader header(3, Http2FrameType::WINDOW_UPDATE, 0, 1);
786 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
787 }
788
TEST_F(Http2FrameDecoderTest,AltSvcTruncatedOriginLength)789 TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOriginLength) {
790 const char kFrameData[] = {
791 '\x00', '\x00', '\x01', // Payload length: 3
792 '\x0a', // ALTSVC
793 '\x00', // Flags: none
794 '\x00', '\x00', '\x00', '\x02', // Stream ID: 2
795 '\x00', // Origin Length: truncated
796 };
797 Http2FrameHeader header(1, Http2FrameType::ALTSVC, 0, 2);
798 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
799 }
800
TEST_F(Http2FrameDecoderTest,AltSvcTruncatedOrigin)801 TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOrigin) {
802 const char kFrameData[] = {
803 '\x00', '\x00', '\x05', // Payload length: 3
804 '\x0a', // ALTSVC
805 '\x00', // Flags: none
806 '\x00', '\x00', '\x00', '\x02', // Stream ID: 2
807 '\x00', '\x04', // Origin Length: 4 (too long)
808 'a', 'b', 'c', // Origin
809 };
810 Http2FrameHeader header(5, Http2FrameType::ALTSVC, 0, 2);
811 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
812 }
813
814 ////////////////////////////////////////////////////////////////////////////////
815 // Payload too long errors.
816
817 // The decoder calls the listener's OnFrameSizeError method if the frame's
818 // payload is longer than the currently configured maximum payload size.
TEST_F(Http2FrameDecoderTest,BeyondMaximum)819 TEST_F(Http2FrameDecoderTest, BeyondMaximum) {
820 maximum_payload_size_ = 2;
821 const char kFrameData[] = {
822 '\x00', '\x00', '\x07', // Payload length: 7
823 '\x00', // DATA
824 '\x09', // Flags: END_STREAM | PADDED
825 '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID)
826 '\x03', // Pad Len
827 'a', 'b', 'c', // Data
828 '\x00', '\x00', '\x00', // Padding
829 };
830 Http2FrameHeader header(7, Http2FrameType::DATA,
831 Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED,
832 2);
833 FrameParts expected(header);
834 expected.SetHasFrameSizeError(true);
835 auto validator = [&expected, this](const DecodeBuffer& input,
836 DecodeStatus status) -> AssertionResult {
837 HTTP2_VERIFY_EQ(status, DecodeStatus::kDecodeError);
838 // The decoder detects this error after decoding the header, and without
839 // trying to decode the payload.
840 HTTP2_VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize());
841 return VerifyCollected(expected);
842 };
843 ResetDecodeSpeedCounters();
844 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData),
845 validator));
846 EXPECT_GT(fast_decode_count_, 0u);
847 EXPECT_GT(slow_decode_count_, 0u);
848 }
849
TEST_F(Http2FrameDecoderTest,PriorityTooLong)850 TEST_F(Http2FrameDecoderTest, PriorityTooLong) {
851 const char kFrameData[] = {
852 '\x00', '\x00', '\x06', // Length: 5
853 '\x02', // Type: PRIORITY
854 '\x00', // Flags: none
855 '\x00', '\x00', '\x00', '\x02', // Stream: 2
856 '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive)
857 '\x10', // Weight: 17
858 '\x00', // Too much
859 };
860 Http2FrameHeader header(6, Http2FrameType::PRIORITY, 0, 2);
861 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
862 }
863
TEST_F(Http2FrameDecoderTest,RstStreamTooLong)864 TEST_F(Http2FrameDecoderTest, RstStreamTooLong) {
865 const char kFrameData[] = {
866 '\x00', '\x00', '\x05', // Length: 4
867 '\x03', // Type: RST_STREAM
868 '\x00', // Flags: none
869 '\x00', '\x00', '\x00', '\x01', // Stream: 1
870 '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR
871 '\x00', // Too much
872 };
873 Http2FrameHeader header(5, Http2FrameType::RST_STREAM, 0, 1);
874 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
875 }
876
TEST_F(Http2FrameDecoderTest,SettingsAckTooLong)877 TEST_F(Http2FrameDecoderTest, SettingsAckTooLong) {
878 const char kFrameData[] = {
879 '\x00', '\x00', '\x06', // Length: 6
880 '\x04', // Type: SETTINGS
881 '\x01', // Flags: ACK
882 '\x00', '\x00', '\x00', '\x00', // Stream: 0
883 '\x00', '\x00', // Extra
884 '\x00', '\x00', '\x00', '\x00', // Extra
885 };
886 Http2FrameHeader header(6, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0);
887 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
888 }
889
TEST_F(Http2FrameDecoderTest,PingAckTooLong)890 TEST_F(Http2FrameDecoderTest, PingAckTooLong) {
891 const char kFrameData[] = {
892 '\x00', '\x00', '\x09', // Length: 8
893 '\x06', // Type: PING
894 '\xff', // Flags: ACK | 0xfe
895 '\x00', '\x00', '\x00', '\x00', // Stream: 0
896 's', 'o', 'm', 'e', // "some"
897 'd', 'a', 't', 'a', // "data"
898 '\x00', // Too much
899 };
900 Http2FrameHeader header(9, Http2FrameType::PING, Http2FrameFlag::ACK, 0);
901 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
902 }
903
TEST_F(Http2FrameDecoderTest,WindowUpdateTooLong)904 TEST_F(Http2FrameDecoderTest, WindowUpdateTooLong) {
905 const char kFrameData[] = {
906 '\x00', '\x00', '\x05', // Length: 5
907 '\x08', // Type: WINDOW_UPDATE
908 '\x0f', // Flags: 0xff (no valid flags)
909 '\x00', '\x00', '\x00', '\x01', // Stream: 1
910 '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit)
911 '\x00', // Too much
912 };
913 Http2FrameHeader header(5, Http2FrameType::WINDOW_UPDATE, 0, 1);
914 EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
915 }
916
917 } // namespace
918 } // namespace test
919 } // namespace http2
920