| Index: net/spdy/spdy_framer_test.cc
|
| diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
|
| index 35b8a46c33f8d74a6fdedd52098fdd886340eea4..84ea0d73119a067c97f8575631631a642a843730 100644
|
| --- a/net/spdy/spdy_framer_test.cc
|
| +++ b/net/spdy/spdy_framer_test.cc
|
| @@ -2805,6 +2805,35 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
|
| CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| }
|
| }
|
| +
|
| + {
|
| + const char kDescription[] =
|
| + "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
|
| +
|
| + const unsigned char kV4FrameData[] = {
|
| + 0x00, 0x00, 0x15, 0x01, // Headers
|
| + 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
|
| + // 0x7fffffff
|
| + 0xff, 0x05, 0x00, 0x00, // Pad length field
|
| + 0x03, 0x66, 0x6f, 0x6f, // .foo
|
| + 0x00, 0x03, 0x66, 0x6f, // @.fo
|
| + 0x6f, 0x03, 0x62, 0x61, // o.ba
|
| + 0x72, // r
|
| + // Padding payload
|
| + 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + };
|
| + SpdyHeadersIR headers_ir(0x7fffffff);
|
| + headers_ir.set_fin(true);
|
| + headers_ir.SetHeader("", "foo");
|
| + headers_ir.SetHeader("foo", "bar");
|
| + headers_ir.set_padding_len(6);
|
| + scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| + if (IsSpdy2() || IsSpdy3()) {
|
| + // Padding is not supported.
|
| + } else {
|
| + CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| + }
|
| + }
|
| }
|
|
|
| // TODO(phajdan.jr): Clean up after we no longer need
|
| @@ -2982,27 +3011,98 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
|
| return;
|
| }
|
|
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - const char kDescription[] = "PUSH_PROMISE frame";
|
| + {
|
| + // Test framing PUSH_PROMISE without padding.
|
| + SpdyFramer framer(spdy_version_);
|
| + framer.set_enable_compression(false);
|
| + const char kDescription[] = "PUSH_PROMISE frame without padding";
|
| +
|
| + const unsigned char kFrameData[] = {
|
| + 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
|
| + 0x04, 0x00, 0x00, 0x00, // END_HEADERS
|
| + 0x2a, 0x00, 0x00, 0x00, // Stream 42
|
| + 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
|
| + 0x61, 0x72, 0x03, 0x66, // ar.f
|
| + 0x6f, 0x6f, 0x00, 0x03, // oo@.
|
| + 0x66, 0x6f, 0x6f, 0x03, // foo.
|
| + 0x62, 0x61, 0x72, // bar
|
| + };
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x16, 0x05, 0x04, // PUSH_PROMISE: END_HEADERS
|
| - 0x00, 0x00, 0x00, 0x2a, // Stream 42
|
| - 0x00, 0x00, 0x00, 0x39, // Promised stream 57
|
| - 0x00, 0x03, 0x62, 0x61, // @.ba
|
| - 0x72, 0x03, 0x66, 0x6f, // r.fo
|
| - 0x6f, 0x00, 0x03, 0x66, // o@.f
|
| - 0x6f, 0x6f, 0x03, 0x62, // oo.b
|
| - 0x61, 0x72, // ar
|
| - };
|
| + SpdyPushPromiseIR push_promise(42, 57);
|
| + push_promise.SetHeader("bar", "foo");
|
| + push_promise.SetHeader("foo", "bar");
|
| + scoped_ptr<SpdySerializedFrame> frame(
|
| + framer.SerializePushPromise(push_promise));
|
| + CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + }
|
|
|
| - SpdyPushPromiseIR push_promise(42, 57);
|
| - push_promise.SetHeader("bar", "foo");
|
| - push_promise.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + {
|
| + // Test framing PUSH_PROMISE with one byte of padding.
|
| + SpdyFramer framer(spdy_version_);
|
| + framer.set_enable_compression(false);
|
| + const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
|
| +
|
| + const unsigned char kFrameData[] = {
|
| + 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
|
| + 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
|
| + 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
|
| + 0x00, 0x39, 0x00, 0x03, // Promised stream 57
|
| + 0x62, 0x61, 0x72, 0x03, // bar.
|
| + 0x66, 0x6f, 0x6f, 0x00, // foo@
|
| + 0x03, 0x66, 0x6f, 0x6f, // .foo
|
| + 0x03, 0x62, 0x61, 0x72, // .bar
|
| + };
|
| +
|
| + SpdyPushPromiseIR push_promise(42, 57);
|
| + push_promise.set_padding_len(1);
|
| + push_promise.SetHeader("bar", "foo");
|
| + push_promise.SetHeader("foo", "bar");
|
| + scoped_ptr<SpdySerializedFrame> frame(
|
| + framer.SerializePushPromise(push_promise));
|
| + CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + }
|
| +
|
| + {
|
| + // Test framing PUSH_PROMISE with 177 bytes of padding.
|
| + SpdyFramer framer(spdy_version_);
|
| + framer.set_enable_compression(false);
|
| + const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
|
| +
|
| + const unsigned char kFrameData[] = {
|
| + 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
|
| + 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
|
| + 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
|
| + 0x00, 0x39, 0x00, 0x03, // Promised stream 57
|
| + 0x62, 0x61, 0x72, 0x03, // bar.
|
| + 0x66, 0x6f, 0x6f, 0x00, // foo@
|
| + 0x03, 0x66, 0x6f, 0x6f, // .foo
|
| + 0x03, 0x62, 0x61, 0x72, // .bar
|
| + // Padding of 176 0x00(s).
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| + };
|
| +
|
| + SpdyPushPromiseIR push_promise(42, 57);
|
| + push_promise.set_padding_len(177);
|
| + push_promise.SetHeader("bar", "foo");
|
| + push_promise.SetHeader("foo", "bar");
|
| + scoped_ptr<SpdySerializedFrame> frame(
|
| + framer.SerializePushPromise(push_promise));
|
| + CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + }
|
| }
|
|
|
| TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
|
| @@ -3032,6 +3132,107 @@ TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
|
| CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| }
|
|
|
| +TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
|
| + if (spdy_version_ <= SPDY3) {
|
| + return;
|
| + }
|
| +
|
| + {
|
| + // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
|
| + // padding, cannot hold all the data payload, which is overflowed to the
|
| + // consecutive CONTINUATION frame.
|
| + SpdyFramer framer(spdy_version_);
|
| + framer.set_enable_compression(false);
|
| + const char kDescription[] =
|
| + "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
|
| +
|
| + const unsigned char kPartialPushPromiseFrameData[] = {
|
| + 0x00, 0x03, 0xf6, 0x05, // PUSH_PROMISE
|
| + 0x08, 0x00, 0x00, 0x00, // PADDED
|
| + 0x2a, 0x00, 0x00, 0x00, // Stream 42
|
| + 0x00, 0x39, 0x00, 0x03, // Promised stream 57
|
| + 0x78, 0x78, 0x78, 0x7f, // xxx.
|
| + 0x80, 0x07, 0x78, 0x78, // ..xx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, // xx
|
| + };
|
| +
|
| + const unsigned char kContinuationFrameData[] = {
|
| + 0x00, 0x00, 0x16, 0x09, // CONTINUATION
|
| + 0x04, 0x00, 0x00, 0x00, // END_HEADERS
|
| + 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78, 0x78, 0x78, // xxxx
|
| + 0x78, 0x78,
|
| + };
|
| +
|
| + SpdyPushPromiseIR push_promise(42, 57);
|
| + push_promise.set_padding_len(1);
|
| + string big_value(framer.GetHeaderFragmentMaxSize(), 'x');
|
| + push_promise.SetHeader("xxx", big_value);
|
| + scoped_ptr<SpdySerializedFrame> frame(
|
| + framer.SerializePushPromise(push_promise));
|
| +
|
| + // The entire frame should look like below:
|
| + // Name Length in Byte
|
| + // ------------------------------------------- Begin of PUSH_PROMISE frame
|
| + // PUSH_PROMISE header 9
|
| + // Pad length field 1
|
| + // Promised stream 4
|
| + // Length field of key 2
|
| + // Content of key 3
|
| + // Length field of value 3
|
| + // Part of big_value 16361
|
| + // ------------------------------------------- Begin of CONTINUATION frame
|
| + // CONTINUATION header 9
|
| + // Remaining of big_value 22
|
| + // ------------------------------------------- End
|
| +
|
| + // Length of everything listed above except big_value.
|
| + int len_non_data_payload = 31;
|
| + EXPECT_EQ(framer.GetHeaderFragmentMaxSize() + len_non_data_payload,
|
| + frame->size());
|
| +
|
| + // Partially compare the PUSH_PROMISE frame against the template.
|
| + const unsigned char* frame_data =
|
| + reinterpret_cast<const unsigned char*>(frame->data());
|
| + CompareCharArraysWithHexError(kDescription,
|
| + frame_data,
|
| + arraysize(kPartialPushPromiseFrameData),
|
| + kPartialPushPromiseFrameData,
|
| + arraysize(kPartialPushPromiseFrameData));
|
| +
|
| + // Compare the CONTINUATION frame against the template.
|
| + frame_data += framer.GetHeaderFragmentMaxSize();
|
| + CompareCharArraysWithHexError(kDescription,
|
| + frame_data,
|
| + arraysize(kContinuationFrameData),
|
| + kContinuationFrameData,
|
| + arraysize(kContinuationFrameData));
|
| + }
|
| +}
|
| +
|
| TEST_P(SpdyFramerTest, CreateAltSvc) {
|
| if (spdy_version_ <= SPDY3) {
|
| return;
|
| @@ -3263,6 +3464,7 @@ TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
|
| SpdyFramer framer(spdy_version_);
|
| framer.set_enable_compression(false);
|
| SpdyHeadersIR headers(1);
|
| + headers.set_padding_len(256);
|
|
|
| // Exact payload length will change with HPACK, but this should be long
|
| // enough to cause an overflow.
|
| @@ -3291,6 +3493,7 @@ TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
|
| SpdyFramer framer(spdy_version_);
|
| framer.set_enable_compression(false);
|
| SpdyPushPromiseIR push_promise(1, 2);
|
| + push_promise.set_padding_len(256);
|
|
|
| // Exact payload length will change with HPACK, but this should be long
|
| // enough to cause an overflow.
|
| @@ -3729,7 +3932,7 @@ TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
|
| CHECK_EQ(framer.GetDataFrameMinimumSize(),
|
| framer.ProcessInput(frame->data(),
|
| framer.GetDataFrameMinimumSize()));
|
| - CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_PADDING_LENGTH);
|
| + CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
|
| CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
|
| bytes_consumed += framer.GetDataFrameMinimumSize();
|
|
|
| @@ -3966,31 +4169,31 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
|
| }
|
|
|
| const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x17, 0x05, 0x08, // PUSH_PROMISE: PADDED
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x00, 0x00, 0x2A, // Promised stream 42
|
| - 0x02, // Padding of 2.
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| - 0x00, 0x00,
|
| -
|
| - 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x08, 0x62, 0x61, 0x7a,
|
| - 0x3d, 0x62, 0x69, 0x6e,
|
| - 0x67, 0x00, 0x06, 0x63,
|
| -
|
| - 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| + 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
|
| + 0x08, 0x00, 0x00, 0x00, // PADDED
|
| + 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
|
| + 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
|
| + 0x63, 0x6f, 0x6f, 0x6b,
|
| + 0x69, 0x65, 0x07, 0x66,
|
| + 0x6f, 0x6f, 0x3d, 0x62,
|
| + 0x61, 0x72, 0x00, 0x00,
|
| +
|
| + 0x00, 0x00, 0x14, 0x09, // CONTINUATION
|
| + 0x00, 0x00, 0x00, 0x00,
|
| + 0x01, 0x00, 0x06, 0x63, // Stream 1
|
| 0x6f, 0x6f, 0x6b, 0x69,
|
| - 0x65, 0x00, 0x00, 0x04,
|
| - 0x6e, 0x61, 0x6d, 0x65,
|
| - 0x05, 0x76, 0x61, 0x6c,
|
| - 0x75, 0x65,
|
| + 0x65, 0x08, 0x62, 0x61,
|
| + 0x7a, 0x3d, 0x62, 0x69,
|
| + 0x6e, 0x67, 0x00, 0x06,
|
| + 0x63,
|
| +
|
| + 0x00, 0x00, 0x12, 0x09, // CONTINUATION
|
| + 0x04, 0x00, 0x00, 0x00, // END_HEADERS
|
| + 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
|
| + 0x69, 0x65, 0x00, 0x00,
|
| + 0x04, 0x6e, 0x61, 0x6d,
|
| + 0x65, 0x05, 0x76, 0x61,
|
| + 0x6c, 0x75, 0x65,
|
| };
|
|
|
| SpdyFramer framer(spdy_version_);
|
|
|