diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-17 17:24:03 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-06-22 07:51:41 +0000 |
commit | 774f54339e5db91f785733232d3950366db65d07 (patch) | |
tree | 068e1b47bd1af94d77094ed12b604a6b83d9c22a /chromium/net/third_party/quiche/src/http2/decoder | |
parent | f7eaed5286974984ba5f9e3189d8f49d03e99f81 (diff) | |
download | qtwebengine-chromium-774f54339e5db91f785733232d3950366db65d07.tar.gz |
BASELINE: Update Chromium to 102.0.5005.57
Change-Id: I885f714bb40ee724c28f94ca6bd8dbdb39915158
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/third_party/quiche/src/http2/decoder')
65 files changed, 0 insertions, 9162 deletions
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer.cc b/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer.cc deleted file mode 100644 index 2d1b6f7a1a9..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/decode_buffer.h" - -namespace http2 { - -uint8_t DecodeBuffer::DecodeUInt8() { - return static_cast<uint8_t>(DecodeChar()); -} - -uint16_t DecodeBuffer::DecodeUInt16() { - QUICHE_DCHECK_LE(2u, Remaining()); - const uint8_t b1 = DecodeUInt8(); - const uint8_t b2 = DecodeUInt8(); - // Note that chars are automatically promoted to ints during arithmetic, - // so the b1 << 8 doesn't end up as zero before being or-ed with b2. - // And the left-shift operator has higher precedence than the or operator. - return b1 << 8 | b2; -} - -uint32_t DecodeBuffer::DecodeUInt24() { - QUICHE_DCHECK_LE(3u, Remaining()); - const uint8_t b1 = DecodeUInt8(); - const uint8_t b2 = DecodeUInt8(); - const uint8_t b3 = DecodeUInt8(); - return b1 << 16 | b2 << 8 | b3; -} - -uint32_t DecodeBuffer::DecodeUInt31() { - QUICHE_DCHECK_LE(4u, Remaining()); - const uint8_t b1 = DecodeUInt8() & 0x7f; // Mask out the high order bit. - const uint8_t b2 = DecodeUInt8(); - const uint8_t b3 = DecodeUInt8(); - const uint8_t b4 = DecodeUInt8(); - return b1 << 24 | b2 << 16 | b3 << 8 | b4; -} - -uint32_t DecodeBuffer::DecodeUInt32() { - QUICHE_DCHECK_LE(4u, Remaining()); - const uint8_t b1 = DecodeUInt8(); - const uint8_t b2 = DecodeUInt8(); - const uint8_t b3 = DecodeUInt8(); - const uint8_t b4 = DecodeUInt8(); - return b1 << 24 | b2 << 16 | b3 << 8 | b4; -} - -#ifndef NDEBUG -void DecodeBuffer::set_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset) { - QUICHE_DCHECK_EQ(this, subset); - base->set_subset(subset); -} -void DecodeBuffer::clear_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset) { - QUICHE_DCHECK_EQ(this, subset); - base->clear_subset(subset); -} -void DecodeBuffer::set_subset(const DecodeBufferSubset* subset) { - QUICHE_DCHECK(subset != nullptr); - QUICHE_DCHECK_EQ(subset_, nullptr) << "There is already a subset"; - subset_ = subset; -} -void DecodeBuffer::clear_subset(const DecodeBufferSubset* subset) { - QUICHE_DCHECK(subset != nullptr); - QUICHE_DCHECK_EQ(subset_, subset); - subset_ = nullptr; -} -void DecodeBufferSubset::DebugSetup() { - start_base_offset_ = base_buffer_->Offset(); - max_base_offset_ = start_base_offset_ + FullSize(); - QUICHE_DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); - - // Ensure that there is only one DecodeBufferSubset at a time for a base. - set_subset_of_base(base_buffer_, this); -} -void DecodeBufferSubset::DebugTearDown() { - // Ensure that the base hasn't been modified. - QUICHE_DCHECK_EQ(start_base_offset_, base_buffer_->Offset()) - << "The base buffer was modified"; - - // Ensure that we haven't gone beyond the maximum allowed offset. - size_t offset = Offset(); - QUICHE_DCHECK_LE(offset, FullSize()); - QUICHE_DCHECK_LE(start_base_offset_ + offset, max_base_offset_); - QUICHE_DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); - - clear_subset_of_base(base_buffer_, this); -} -#endif - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer.h b/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer.h deleted file mode 100644 index 3d0f5d5fddf..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_DECODE_BUFFER_H_ -#define QUICHE_HTTP2_DECODER_DECODE_BUFFER_H_ - -// DecodeBuffer provides primitives for decoding various integer types found in -// HTTP/2 frames. It wraps a byte array from which we can read and decode -// serialized HTTP/2 frames, or parts thereof. DecodeBuffer is intended only for -// stack allocation, where the caller is typically going to use the DecodeBuffer -// instance as part of decoding the entire buffer before returning to its own -// caller. - -#include <stddef.h> - -#include <algorithm> -#include <cstdint> - -#include "absl/strings/string_view.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -class DecodeBufferSubset; - -class QUICHE_EXPORT_PRIVATE DecodeBuffer { - public: - // We assume the decode buffers will typically be modest in size (i.e. often a - // few KB, perhaps as high as 100KB). Let's make sure during testing that we - // don't go very high, with 32MB selected rather arbitrarily. This is exposed - // to support testing. - static constexpr size_t kMaxDecodeBufferLength = 1 << 25; - - DecodeBuffer(const char* buffer, size_t len) - : buffer_(buffer), cursor_(buffer), beyond_(buffer + len) { - QUICHE_DCHECK(buffer != nullptr); - QUICHE_DCHECK_LE(len, kMaxDecodeBufferLength); - } - explicit DecodeBuffer(absl::string_view s) - : DecodeBuffer(s.data(), s.size()) {} - // Constructor for character arrays, typically in tests. For example: - // const char input[] = { 0x11 }; - // DecodeBuffer b(input); - template <size_t N> - explicit DecodeBuffer(const char (&buf)[N]) : DecodeBuffer(buf, N) {} - - DecodeBuffer(const DecodeBuffer&) = delete; - DecodeBuffer operator=(const DecodeBuffer&) = delete; - - bool Empty() const { return cursor_ >= beyond_; } - bool HasData() const { return cursor_ < beyond_; } - size_t Remaining() const { - QUICHE_DCHECK_LE(cursor_, beyond_); - return beyond_ - cursor_; - } - size_t Offset() const { return cursor_ - buffer_; } - size_t FullSize() const { return beyond_ - buffer_; } - - // Returns the minimum of the number of bytes remaining in this DecodeBuffer - // and |length|, in support of determining how much of some structure/payload - // is in this DecodeBuffer. - size_t MinLengthRemaining(size_t length) const { - return std::min(length, Remaining()); - } - - // For string decoding, returns a pointer to the next byte/char to be decoded. - const char* cursor() const { return cursor_; } - // Advances the cursor (pointer to the next byte/char to be decoded). - void AdvanceCursor(size_t amount) { - QUICHE_DCHECK_LE(amount, - Remaining()); // Need at least that much remaining. - QUICHE_DCHECK_EQ(subset_, nullptr) - << "Access via subset only when present."; - cursor_ += amount; - } - - // Only call methods starting "Decode" when there is enough input remaining. - char DecodeChar() { - QUICHE_DCHECK_LE(1u, Remaining()); // Need at least one byte remaining. - QUICHE_DCHECK_EQ(subset_, nullptr) - << "Access via subset only when present."; - return *cursor_++; - } - - uint8_t DecodeUInt8(); - uint16_t DecodeUInt16(); - uint32_t DecodeUInt24(); - - // For 31-bit unsigned integers, where the 32nd bit is reserved for future - // use (i.e. the high-bit of the first byte of the encoding); examples: - // the Stream Id in a frame header or the Window Size Increment in a - // WINDOW_UPDATE frame. - uint32_t DecodeUInt31(); - - uint32_t DecodeUInt32(); - - protected: -#ifndef NDEBUG - // These are part of validating during tests that there is at most one - // DecodeBufferSubset instance at a time for any DecodeBuffer instance. - void set_subset_of_base(DecodeBuffer* base, const DecodeBufferSubset* subset); - void clear_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset); -#endif - - private: -#ifndef NDEBUG - void set_subset(const DecodeBufferSubset* subset); - void clear_subset(const DecodeBufferSubset* subset); -#endif - - // Prevent heap allocation of DecodeBuffer. - static void* operator new(size_t s); - static void* operator new[](size_t s); - static void operator delete(void* p); - static void operator delete[](void* p); - - const char* const buffer_; - const char* cursor_; - const char* const beyond_; - const DecodeBufferSubset* subset_ = nullptr; // Used for QUICHE_DCHECKs. -}; - -// DecodeBufferSubset is used when decoding a known sized chunk of data, which -// starts at base->cursor(), and continues for subset_len, which may be -// entirely in |base|, or may extend beyond it (hence the MinLengthRemaining -// in the constructor). -// There are two benefits to using DecodeBufferSubset: it ensures that the -// cursor of |base| is advanced when the subset's destructor runs, and it -// ensures that the consumer of the subset can't go beyond the subset which -// it is intended to decode. -// There must be only a single DecodeBufferSubset at a time for a base -// DecodeBuffer, though they can be nested (i.e. a DecodeBufferSubset's -// base may itself be a DecodeBufferSubset). This avoids the AdvanceCursor -// being called erroneously. -class QUICHE_EXPORT_PRIVATE DecodeBufferSubset : public DecodeBuffer { - public: - DecodeBufferSubset(DecodeBuffer* base, size_t subset_len) - : DecodeBuffer(base->cursor(), base->MinLengthRemaining(subset_len)), - base_buffer_(base) { -#ifndef NDEBUG - DebugSetup(); -#endif - } - - DecodeBufferSubset(const DecodeBufferSubset&) = delete; - DecodeBufferSubset operator=(const DecodeBufferSubset&) = delete; - - ~DecodeBufferSubset() { - size_t offset = Offset(); -#ifndef NDEBUG - DebugTearDown(); -#endif - base_buffer_->AdvanceCursor(offset); - } - - private: - DecodeBuffer* const base_buffer_; -#ifndef NDEBUG - size_t start_base_offset_; // Used for QUICHE_DCHECKs. - size_t max_base_offset_; // Used for QUICHE_DCHECKs. - - void DebugSetup(); - void DebugTearDown(); -#endif -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_DECODE_BUFFER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer_test.cc deleted file mode 100644 index 54c0fea371b..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_buffer_test.cc +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/decode_buffer.h" - -#include <functional> - -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "http2/test_tools/http2_random.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -namespace { - -enum class TestEnumClass32 { - kValue1 = 1, - kValue99 = 99, - kValue1M = 1000000, -}; - -enum class TestEnumClass8 { - kValue1 = 1, - kValue2 = 1, - kValue99 = 99, - kValue255 = 255, -}; - -enum TestEnum8 { - kMaskLo = 0x01, - kMaskHi = 0x80, -}; - -struct TestStruct { - uint8_t f1; - uint16_t f2; - uint32_t f3; // Decoded as a uint24 - uint32_t f4; - uint32_t f5; // Decoded as if uint31 - TestEnumClass32 f6; - TestEnumClass8 f7; - TestEnum8 f8; -}; - -class DecodeBufferTest : public QuicheTest { - protected: - Http2Random random_; - uint32_t decode_offset_; -}; - -TEST_F(DecodeBufferTest, DecodesFixedInts) { - const char data[] = "\x01\x12\x23\x34\x45\x56\x67\x78\x89\x9a"; - DecodeBuffer b1(data, strlen(data)); - EXPECT_EQ(1, b1.DecodeUInt8()); - EXPECT_EQ(0x1223u, b1.DecodeUInt16()); - EXPECT_EQ(0x344556u, b1.DecodeUInt24()); - EXPECT_EQ(0x6778899Au, b1.DecodeUInt32()); -} - -// Make sure that DecodeBuffer is not copying input, just pointing into -// provided input buffer. -TEST_F(DecodeBufferTest, HasNotCopiedInput) { - const char data[] = "ab"; - DecodeBuffer b1(data, 2); - - EXPECT_EQ(2u, b1.Remaining()); - EXPECT_EQ(0u, b1.Offset()); - EXPECT_FALSE(b1.Empty()); - EXPECT_EQ(data, b1.cursor()); // cursor points to input buffer - EXPECT_TRUE(b1.HasData()); - - b1.AdvanceCursor(1); - - EXPECT_EQ(1u, b1.Remaining()); - EXPECT_EQ(1u, b1.Offset()); - EXPECT_FALSE(b1.Empty()); - EXPECT_EQ(&data[1], b1.cursor()); - EXPECT_TRUE(b1.HasData()); - - b1.AdvanceCursor(1); - - EXPECT_EQ(0u, b1.Remaining()); - EXPECT_EQ(2u, b1.Offset()); - EXPECT_TRUE(b1.Empty()); - EXPECT_EQ(&data[2], b1.cursor()); - EXPECT_FALSE(b1.HasData()); - - DecodeBuffer b2(data, 0); - - EXPECT_EQ(0u, b2.Remaining()); - EXPECT_EQ(0u, b2.Offset()); - EXPECT_TRUE(b2.Empty()); - EXPECT_EQ(data, b2.cursor()); - EXPECT_FALSE(b2.HasData()); -} - -// DecodeBufferSubset can't go beyond the end of the base buffer. -TEST_F(DecodeBufferTest, DecodeBufferSubsetLimited) { - const char data[] = "abc"; - DecodeBuffer base(data, 3); - base.AdvanceCursor(1); - DecodeBufferSubset subset(&base, 100); - EXPECT_EQ(2u, subset.FullSize()); -} - -// DecodeBufferSubset advances the cursor of its base upon destruction. -TEST_F(DecodeBufferTest, DecodeBufferSubsetAdvancesCursor) { - const char data[] = "abc"; - const size_t size = sizeof(data) - 1; - EXPECT_EQ(3u, size); - DecodeBuffer base(data, size); - { - // First no change to the cursor. - DecodeBufferSubset subset(&base, size + 100); - EXPECT_EQ(size, subset.FullSize()); - EXPECT_EQ(base.FullSize(), subset.FullSize()); - EXPECT_EQ(0u, subset.Offset()); - } - EXPECT_EQ(0u, base.Offset()); - EXPECT_EQ(size, base.Remaining()); -} - -// Make sure that DecodeBuffer ctor complains about bad args. -#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) -TEST(DecodeBufferDeathTest, NonNullBufferRequired) { - EXPECT_DEBUG_DEATH({ DecodeBuffer b(nullptr, 3); }, "nullptr"); -} - -// Make sure that DecodeBuffer ctor complains about bad args. -TEST(DecodeBufferDeathTest, ModestBufferSizeRequired) { - EXPECT_DEBUG_DEATH( - { - // This depends on being able to allocate a fairly large array on the - // stack. If that fails, we can instead do this: - // - // std::string data(DecodeBuffer::kMaxDecodeBufferLength + 1, ' '); - // DecodeBuffer b(data.data(), data.size()); - - const char data[DecodeBuffer::kMaxDecodeBufferLength + 1] = {}; - DecodeBuffer b(data, sizeof data); - }, - "Max.*Length"); -} - -// Make sure that DecodeBuffer detects advance beyond end, in debug mode. -TEST(DecodeBufferDeathTest, LimitedAdvance) { - { - // Advance right up to end is OK. - const char data[] = "abc"; - DecodeBuffer b(data, 3); - b.AdvanceCursor(3); // OK - EXPECT_TRUE(b.Empty()); - } - EXPECT_DEBUG_DEATH( - { - // Going beyond is not OK. - const char data[] = "abc"; - DecodeBuffer b(data, 3); - b.AdvanceCursor(4); - }, - "4 vs. 3"); -} - -// Make sure that DecodeBuffer detects decode beyond end, in debug mode. -TEST(DecodeBufferDeathTest, DecodeUInt8PastEnd) { - const char data[] = {0x12, 0x23}; - DecodeBuffer b(data, sizeof data); - EXPECT_EQ(2u, b.FullSize()); - EXPECT_EQ(0x1223, b.DecodeUInt16()); - EXPECT_DEBUG_DEATH({ b.DecodeUInt8(); }, "1 vs. 0"); -} - -// Make sure that DecodeBuffer detects decode beyond end, in debug mode. -TEST(DecodeBufferDeathTest, DecodeUInt16OverEnd) { - const char data[] = {0x12, 0x23, 0x34}; - DecodeBuffer b(data, sizeof data); - EXPECT_EQ(3u, b.FullSize()); - EXPECT_EQ(0x1223, b.DecodeUInt16()); - EXPECT_DEBUG_DEATH({ b.DecodeUInt16(); }, "2 vs. 1"); -} - -// Make sure that DecodeBuffer doesn't agree with having two subsets. -TEST(DecodeBufferSubsetDeathTest, TwoSubsets) { - const char data[] = "abc"; - DecodeBuffer base(data, 3); - DecodeBufferSubset subset1(&base, 1); - EXPECT_DEBUG_DEATH({ DecodeBufferSubset subset2(&base, 1); }, - "There is already a subset"); -} - -// Make sure that DecodeBufferSubset notices when the base's cursor has moved. -TEST(DecodeBufferSubsetDeathTest, BaseCursorAdvanced) { - const char data[] = "abc"; - DecodeBuffer base(data, 3); - base.AdvanceCursor(1); - EXPECT_DEBUG_DEATH( - { - DecodeBufferSubset subset1(&base, 2); - base.AdvanceCursor(1); - }, - "Access via subset only when present"); -} -#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures.cc b/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures.cc deleted file mode 100644 index a5582c24991..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures.cc +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/decode_http2_structures.h" - -#include <cstdint> -#include <cstring> - -#include "http2/decoder/decode_buffer.h" -#include "http2/http2_constants.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -// Http2FrameHeader decoding: - -void DoDecode(Http2FrameHeader* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2FrameHeader::EncodedSize(), b->Remaining()); - out->payload_length = b->DecodeUInt24(); - out->type = static_cast<Http2FrameType>(b->DecodeUInt8()); - out->flags = static_cast<Http2FrameFlag>(b->DecodeUInt8()); - out->stream_id = b->DecodeUInt31(); -} - -// Http2PriorityFields decoding: - -void DoDecode(Http2PriorityFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2PriorityFields::EncodedSize(), b->Remaining()); - uint32_t stream_id_and_flag = b->DecodeUInt32(); - out->stream_dependency = stream_id_and_flag & StreamIdMask(); - if (out->stream_dependency == stream_id_and_flag) { - out->is_exclusive = false; - } else { - out->is_exclusive = true; - } - // Note that chars are automatically promoted to ints during arithmetic, - // so 255 + 1 doesn't end up as zero. - out->weight = b->DecodeUInt8() + 1; -} - -// Http2RstStreamFields decoding: - -void DoDecode(Http2RstStreamFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2RstStreamFields::EncodedSize(), b->Remaining()); - out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32()); -} - -// Http2SettingFields decoding: - -void DoDecode(Http2SettingFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2SettingFields::EncodedSize(), b->Remaining()); - out->parameter = static_cast<Http2SettingsParameter>(b->DecodeUInt16()); - out->value = b->DecodeUInt32(); -} - -// Http2PushPromiseFields decoding: - -void DoDecode(Http2PushPromiseFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2PushPromiseFields::EncodedSize(), b->Remaining()); - out->promised_stream_id = b->DecodeUInt31(); -} - -// Http2PingFields decoding: - -void DoDecode(Http2PingFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2PingFields::EncodedSize(), b->Remaining()); - memcpy(out->opaque_bytes, b->cursor(), Http2PingFields::EncodedSize()); - b->AdvanceCursor(Http2PingFields::EncodedSize()); -} - -// Http2GoAwayFields decoding: - -void DoDecode(Http2GoAwayFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2GoAwayFields::EncodedSize(), b->Remaining()); - out->last_stream_id = b->DecodeUInt31(); - out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32()); -} - -// Http2WindowUpdateFields decoding: - -void DoDecode(Http2WindowUpdateFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2WindowUpdateFields::EncodedSize(), b->Remaining()); - out->window_size_increment = b->DecodeUInt31(); -} - -// Http2PriorityUpdateFields decoding: - -void DoDecode(Http2PriorityUpdateFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2PriorityUpdateFields::EncodedSize(), b->Remaining()); - out->prioritized_stream_id = b->DecodeUInt31(); -} - -// Http2AltSvcFields decoding: - -void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b) { - QUICHE_DCHECK_NE(nullptr, out); - QUICHE_DCHECK_NE(nullptr, b); - QUICHE_DCHECK_LE(Http2AltSvcFields::EncodedSize(), b->Remaining()); - out->origin_length = b->DecodeUInt16(); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures.h b/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures.h deleted file mode 100644 index 9b26d330741..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_ -#define QUICHE_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_ - -// Provides functions for decoding the fixed size structures in the HTTP/2 spec. - -#include "http2/decoder/decode_buffer.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -// DoDecode(STRUCTURE* out, DecodeBuffer* b) decodes the structure from start -// to end, advancing the cursor by STRUCTURE::EncodedSize(). The decode buffer -// must be large enough (i.e. b->Remaining() >= STRUCTURE::EncodedSize()). - -QUICHE_EXPORT_PRIVATE void DoDecode(Http2FrameHeader* out, DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2PriorityFields* out, DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2RstStreamFields* out, DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2SettingFields* out, DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2PushPromiseFields* out, - DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2PingFields* out, DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2GoAwayFields* out, DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2WindowUpdateFields* out, - DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b); -QUICHE_EXPORT_PRIVATE void DoDecode(Http2PriorityUpdateFields* out, - DecodeBuffer* b); - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures_test.cc deleted file mode 100644 index 89833e58ec9..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_http2_structures_test.cc +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/decode_http2_structures.h" - -// Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined -// in http2/http2_structures.h). - -#include <stddef.h> - -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -namespace { - -template <typename T, size_t N> -absl::string_view ToStringPiece(T (&data)[N]) { - return absl::string_view(reinterpret_cast<const char*>(data), N * sizeof(T)); -} - -template <class S> -std::string SerializeStructure(const S& s) { - Http2FrameBuilder fb; - fb.Append(s); - EXPECT_EQ(S::EncodedSize(), fb.size()); - return fb.buffer(); -} - -template <class S> -class StructureDecoderTest : public QuicheTest { - protected: - typedef S Structure; - - StructureDecoderTest() : random_(), random_decode_count_(100) {} - - // Set the fields of |*p| to random values. - void Randomize(S* p) { ::http2::test::Randomize(p, &random_); } - - // Fully decodes the Structure at the start of data, and confirms it matches - // *expected (if provided). - void DecodeLeadingStructure(const S* expected, absl::string_view data) { - ASSERT_LE(S::EncodedSize(), data.size()); - DecodeBuffer db(data); - Randomize(&structure_); - DoDecode(&structure_, &db); - EXPECT_EQ(db.Offset(), S::EncodedSize()); - if (expected != nullptr) { - EXPECT_EQ(structure_, *expected); - } - } - - template <size_t N> - void DecodeLeadingStructure(const char (&data)[N]) { - DecodeLeadingStructure(nullptr, absl::string_view(data, N)); - } - - // Encode the structure |in_s| into bytes, then decode the bytes - // and validate that the decoder produced the same field values. - void EncodeThenDecode(const S& in_s) { - std::string bytes = SerializeStructure(in_s); - EXPECT_EQ(S::EncodedSize(), bytes.size()); - DecodeLeadingStructure(&in_s, bytes); - } - - // Generate - void TestDecodingRandomizedStructures(size_t count) { - for (size_t i = 0; i < count && !HasFailure(); ++i) { - Structure input; - Randomize(&input); - EncodeThenDecode(input); - } - } - - void TestDecodingRandomizedStructures() { - TestDecodingRandomizedStructures(random_decode_count_); - } - - Http2Random random_; - const size_t random_decode_count_; - uint32_t decode_offset_ = 0; - S structure_; - size_t fast_decode_count_ = 0; - size_t slow_decode_count_ = 0; -}; - -class FrameHeaderDecoderTest : public StructureDecoderTest<Http2FrameHeader> {}; - -TEST_F(FrameHeaderDecoderTest, DecodesLiteral) { - { - // Realistic input. - const char kData[] = { - '\x00', '\x00', '\x05', // Payload length: 5 - '\x01', // Frame type: HEADERS - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x04', // Padding length: 4 - '\x00', '\x00', '\x00', '\x00', // Padding bytes - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(5u, structure_.payload_length); - EXPECT_EQ(Http2FrameType::HEADERS, structure_.type); - EXPECT_EQ(Http2FrameFlag::PADDED, structure_.flags); - EXPECT_EQ(1u, structure_.stream_id); - } - } - { - // Unlikely input. - const char kData[] = { - '\xff', '\xff', '\xff', // Payload length: uint24 max - '\xff', // Frame type: Unknown - '\xff', // Flags: Unknown/All - '\xff', '\xff', '\xff', '\xff', // Stream ID: uint31 max, plus R-bit - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ((1u << 24) - 1, structure_.payload_length); - EXPECT_EQ(static_cast<Http2FrameType>(255), structure_.type); - EXPECT_EQ(255, structure_.flags); - EXPECT_EQ(0x7FFFFFFFu, structure_.stream_id); - } - } -} - -TEST_F(FrameHeaderDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class PriorityFieldsDecoderTest - : public StructureDecoderTest<Http2PriorityFields> {}; - -TEST_F(PriorityFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x80', '\x00', '\x00', '\x05', // Exclusive (yes) and Dependency (5) - '\xff', // Weight: 256 (after adding 1) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(5u, structure_.stream_dependency); - EXPECT_EQ(256u, structure_.weight); - EXPECT_EQ(true, structure_.is_exclusive); - } - } - { - const char kData[] = { - '\x7f', '\xff', - '\xff', '\xff', // Exclusive (no) and Dependency (0x7fffffff) - '\x00', // Weight: 1 (after adding 1) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.stream_dependency); - EXPECT_EQ(1u, structure_.weight); - EXPECT_FALSE(structure_.is_exclusive); - } - } -} - -TEST_F(PriorityFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class RstStreamFieldsDecoderTest - : public StructureDecoderTest<Http2RstStreamFields> {}; - -TEST_F(RstStreamFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_.error_code); - } - } - { - const char kData[] = { - '\xff', '\xff', '\xff', - '\xff', // Error: max uint32 (Unknown error code) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_FALSE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code); - } - } -} - -TEST_F(RstStreamFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class SettingFieldsDecoderTest - : public StructureDecoderTest<Http2SettingFields> {}; - -TEST_F(SettingFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x01', // Setting: HEADER_TABLE_SIZE - '\x00', '\x00', '\x40', '\x00', // Value: 16K - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_TRUE(structure_.IsSupportedParameter()); - EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE, - structure_.parameter); - EXPECT_EQ(1u << 14, structure_.value); - } - } - { - const char kData[] = { - '\x00', '\x00', // Setting: Unknown (0) - '\xff', '\xff', '\xff', '\xff', // Value: max uint32 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_FALSE(structure_.IsSupportedParameter()); - EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_.parameter); - } - } -} - -TEST_F(SettingFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class PushPromiseFieldsDecoderTest - : public StructureDecoderTest<Http2PushPromiseFields> {}; - -TEST_F(PushPromiseFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x01', '\x8a', '\x92', // Promised Stream ID: 101010 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(101010u, structure_.promised_stream_id); - } - } - { - // Promised stream id has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - const char kData[] = { - '\xff', '\xff', '\xff', - '\xff', // Promised Stream ID: max uint31 and R-bit - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.promised_stream_id); - } - } -} - -TEST_F(PushPromiseFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class PingFieldsDecoderTest : public StructureDecoderTest<Http2PingFields> {}; - -TEST_F(PingFieldsDecoderTest, DecodesLiteral) { - { - // Each byte is different, so can detect if order changed. - const char kData[] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(absl::string_view(kData, 8), - ToStringPiece(structure_.opaque_bytes)); - } - } - { - // All zeros, detect problems handling NULs. - const char kData[] = { - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(absl::string_view(kData, 8), - ToStringPiece(structure_.opaque_bytes)); - } - } - { - const char kData[] = { - '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(absl::string_view(kData, 8), - ToStringPiece(structure_.opaque_bytes)); - } - } -} - -TEST_F(PingFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class GoAwayFieldsDecoderTest : public StructureDecoderTest<Http2GoAwayFields> { -}; - -TEST_F(GoAwayFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x00', '\x00', '\x00', // Last Stream ID: 0 - '\x00', '\x00', '\x00', '\x00', // Error: NO_ERROR (0) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(0u, structure_.last_stream_id); - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_.error_code); - } - } - { - const char kData[] = { - '\x00', '\x00', '\x00', '\x01', // Last Stream ID: 1 - '\x00', '\x00', '\x00', '\x0d', // Error: HTTP_1_1_REQUIRED - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(1u, structure_.last_stream_id); - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_.error_code); - } - } - { - const char kData[] = { - '\xff', '\xff', - '\xff', '\xff', // Last Stream ID: max uint31 and R-bit - '\xff', '\xff', - '\xff', '\xff', // Error: max uint32 (Unknown error code) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.last_stream_id); // No high-bit. - EXPECT_FALSE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code); - } - } -} - -TEST_F(GoAwayFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class WindowUpdateFieldsDecoderTest - : public StructureDecoderTest<Http2WindowUpdateFields> {}; - -TEST_F(WindowUpdateFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x01', '\x00', '\x00', // Window Size Increment: 2 ^ 16 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(1u << 16, structure_.window_size_increment); - } - } - { - // Increment must be non-zero, but we need to be able to decode the invalid - // zero to detect it. - const char kData[] = { - '\x00', '\x00', '\x00', '\x00', // Window Size Increment: 0 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(0u, structure_.window_size_increment); - } - } - { - // Increment has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - // clang-format off - const char kData[] = { - // Window Size Increment: max uint31 and R-bit - '\xff', '\xff', '\xff', '\xff', - }; - // clang-format on - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.window_size_increment); - } - } -} - -TEST_F(WindowUpdateFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class AltSvcFieldsDecoderTest : public StructureDecoderTest<Http2AltSvcFields> { -}; - -TEST_F(AltSvcFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x00', // Origin Length: 0 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(0, structure_.origin_length); - } - } - { - const char kData[] = { - '\x00', '\x14', // Origin Length: 20 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(20, structure_.origin_length); - } - } - { - const char kData[] = { - '\xff', '\xff', // Origin Length: uint16 max - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(65535, structure_.origin_length); - } - } -} - -TEST_F(AltSvcFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc b/chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc deleted file mode 100644 index a5d2c6fedb9..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/decode_status.h" - -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, DecodeStatus v) { - switch (v) { - case DecodeStatus::kDecodeDone: - return out << "DecodeDone"; - case DecodeStatus::kDecodeInProgress: - return out << "DecodeInProgress"; - case DecodeStatus::kDecodeError: - return out << "DecodeError"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG(http2_bug_147_1) << "Unknown DecodeStatus " << unknown; - return out << "DecodeStatus(" << unknown << ")"; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_status.h b/chromium/net/third_party/quiche/src/http2/decoder/decode_status.h deleted file mode 100644 index e738ddf2f6a..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/decode_status.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_DECODE_STATUS_H_ -#define QUICHE_HTTP2_DECODER_DECODE_STATUS_H_ - -// Enum DecodeStatus is used to report the status of decoding of many -// types of HTTP/2 and HPACK objects. - -#include <ostream> - -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -enum class DecodeStatus { - // Decoding is done. - kDecodeDone, - - // Decoder needs more input to be able to make progress. - kDecodeInProgress, - - // Decoding failed (e.g. HPACK variable length integer is too large, or - // an HTTP/2 frame has padding declared to be larger than the payload). - kDecodeError, -}; -QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - DecodeStatus v); - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_DECODE_STATUS_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state.cc b/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state.cc deleted file mode 100644 index ee539641dac..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state.cc +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/frame_decoder_state.h" - -namespace http2 { - -DecodeStatus FrameDecoderState::ReadPadLength(DecodeBuffer* db, - bool report_pad_length) { - HTTP2_DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining() - << "; payload_length=" << frame_header().payload_length; - QUICHE_DCHECK(IsPaddable()); - QUICHE_DCHECK(frame_header().IsPadded()); - - // Pad Length is always at the start of the frame, so remaining_payload_ - // should equal payload_length at this point. - const uint32_t total_payload = frame_header().payload_length; - QUICHE_DCHECK_EQ(total_payload, remaining_payload_); - QUICHE_DCHECK_EQ(0u, remaining_padding_); - - if (db->HasData()) { - const uint32_t pad_length = db->DecodeUInt8(); - const uint32_t total_padding = pad_length + 1; - if (total_padding <= total_payload) { - remaining_padding_ = pad_length; - remaining_payload_ = total_payload - total_padding; - if (report_pad_length) { - listener()->OnPadLength(pad_length); - } - return DecodeStatus::kDecodeDone; - } - const uint32_t missing_length = total_padding - total_payload; - // To allow for the possibility of recovery, record the number of - // remaining bytes of the frame's payload (invalid though it is) - // in remaining_payload_. - remaining_payload_ = total_payload - 1; // 1 for sizeof(Pad Length). - remaining_padding_ = 0; - listener()->OnPaddingTooLong(frame_header(), missing_length); - return DecodeStatus::kDecodeError; - } - - if (total_payload == 0) { - remaining_payload_ = 0; - remaining_padding_ = 0; - listener()->OnPaddingTooLong(frame_header(), 1); - return DecodeStatus::kDecodeError; - } - // Need to wait for another buffer. - return DecodeStatus::kDecodeInProgress; -} - -bool FrameDecoderState::SkipPadding(DecodeBuffer* db) { - HTTP2_DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_ - << ", db->Remaining=" << db->Remaining() - << ", header: " << frame_header(); - QUICHE_DCHECK_EQ(remaining_payload_, 0u); - QUICHE_DCHECK(IsPaddable()) << "header: " << frame_header(); - QUICHE_DCHECK(remaining_padding_ == 0 || frame_header().IsPadded()) - << "remaining_padding_=" << remaining_padding_ - << ", header: " << frame_header(); - const size_t avail = AvailablePadding(db); - if (avail > 0) { - listener()->OnPadding(db->cursor(), avail); - db->AdvanceCursor(avail); - remaining_padding_ -= avail; - } - return remaining_padding_ == 0; -} - -DecodeStatus FrameDecoderState::ReportFrameSizeError() { - HTTP2_DVLOG(2) << "FrameDecoderState::ReportFrameSizeError: " - << " remaining_payload_=" << remaining_payload_ - << "; remaining_padding_=" << remaining_padding_ - << ", header: " << frame_header(); - listener()->OnFrameSizeError(frame_header()); - return DecodeStatus::kDecodeError; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state.h b/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state.h deleted file mode 100644 index f0c135786ba..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state.h +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_FRAME_DECODER_STATE_H_ -#define QUICHE_HTTP2_DECODER_FRAME_DECODER_STATE_H_ - -// FrameDecoderState provides state and behaviors in support of decoding -// the common frame header and the payload of all frame types. -// It is an input to all of the payload decoders. - -// TODO(jamessynge): Since FrameDecoderState has far more than state in it, -// rename to FrameDecoderHelper, or similar. - -#include <stddef.h> - -#include <cstdint> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/http2_structure_decoder.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class FrameDecoderStatePeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE FrameDecoderState { - public: - FrameDecoderState() {} - - // Sets the listener which the decoders should call as they decode HTTP/2 - // frames. The listener can be changed at any time, which allows for replacing - // it with a no-op listener when an error is detected, either by the payload - // decoder (OnPaddingTooLong or OnFrameSizeError) or by the "real" listener. - // That in turn allows us to define Http2FrameDecoderListener such that all - // methods have return type void, with no direct way to indicate whether the - // decoder should stop, and to eliminate from the decoder all checks of the - // return value. Instead the listener/caller can simply replace the current - // listener with a no-op listener implementation. - // TODO(jamessynge): Make set_listener private as only Http2FrameDecoder - // and tests need to set it, so it doesn't need to be public. - void set_listener(Http2FrameDecoderListener* listener) { - listener_ = listener; - } - Http2FrameDecoderListener* listener() const { return listener_; } - - // The most recently decoded frame header. - const Http2FrameHeader& frame_header() const { return frame_header_; } - - // Decode a structure in the payload, adjusting remaining_payload_ to account - // for the consumed portion of the payload. Returns kDecodeDone when fully - // decoded, kDecodeError if it ran out of payload before decoding completed, - // and kDecodeInProgress if the decode buffer didn't have enough of the - // remaining payload. - template <class S> - DecodeStatus StartDecodingStructureInPayload(S* out, DecodeBuffer* db) { - HTTP2_DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining() - << "\n\tremaining_payload_=" << remaining_payload_ - << "\n\tneed=" << S::EncodedSize(); - DecodeStatus status = - structure_decoder_.Start(out, db, &remaining_payload_); - if (status != DecodeStatus::kDecodeError) { - return status; - } - HTTP2_DVLOG(2) - << "StartDecodingStructureInPayload: detected frame size error"; - return ReportFrameSizeError(); - } - - // Resume decoding of a structure that has been split across buffers, - // adjusting remaining_payload_ to account for the consumed portion of - // the payload. Returns values are as for StartDecodingStructureInPayload. - template <class S> - DecodeStatus ResumeDecodingStructureInPayload(S* out, DecodeBuffer* db) { - HTTP2_DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining() - << "\n\tremaining_payload_=" << remaining_payload_; - if (structure_decoder_.Resume(out, db, &remaining_payload_)) { - return DecodeStatus::kDecodeDone; - } else if (remaining_payload_ > 0) { - return DecodeStatus::kDecodeInProgress; - } else { - HTTP2_DVLOG(2) - << "ResumeDecodingStructureInPayload: detected frame size error"; - return ReportFrameSizeError(); - } - } - - // Initializes the two remaining* fields, which is needed if the frame's - // payload is split across buffers, or the decoder calls ReadPadLength or - // StartDecodingStructureInPayload, and of course the methods below which - // read those fields, as their names imply. - void InitializeRemainders() { - remaining_payload_ = frame_header().payload_length; - // Note that remaining_total_payload() relies on remaining_padding_ being - // zero for frames that have no padding. - remaining_padding_ = 0; - } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, including any trailing padding. This method must only be called - // after the variables have been initialized, which in practice means once a - // payload decoder has called InitializeRemainders and/or ReadPadLength. - size_t remaining_total_payload() const { - QUICHE_DCHECK(IsPaddable() || remaining_padding_ == 0) << frame_header(); - return remaining_payload_ + remaining_padding_; - } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, excluding any trailing padding. This method must only be called - // after the variable has been initialized, which in practice means once a - // payload decoder has called InitializeRemainders; ReadPadLength will deduct - // the total number of padding bytes from remaining_payload_, including the - // size of the Pad Length field itself (1 byte). - size_t remaining_payload() const { return remaining_payload_; } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, including any trailing padding. This method must only be called if - // the frame type allows padding, and after the variable has been initialized, - // which in practice means once a payload decoder has called - // InitializeRemainders and/or ReadPadLength. - size_t remaining_payload_and_padding() const { - QUICHE_DCHECK(IsPaddable()) << frame_header(); - return remaining_payload_ + remaining_padding_; - } - - // Returns the number of bytes of trailing padding after the payload that - // remain to be decoded. This method must only be called if the frame type - // allows padding, and after the variable has been initialized, which in - // practice means once a payload decoder has called InitializeRemainders, - // and isn't set to a non-zero value until ReadPadLength has been called. - uint32_t remaining_padding() const { - QUICHE_DCHECK(IsPaddable()) << frame_header(); - return remaining_padding_; - } - - // How many bytes of the remaining payload are in db? - size_t AvailablePayload(DecodeBuffer* db) const { - return db->MinLengthRemaining(remaining_payload_); - } - - // How many bytes of the remaining payload and padding are in db? - // Call only for frames whose type is paddable. - size_t AvailablePayloadAndPadding(DecodeBuffer* db) const { - QUICHE_DCHECK(IsPaddable()) << frame_header(); - return db->MinLengthRemaining(remaining_payload_ + remaining_padding_); - } - - // How many bytes of the padding that have not yet been skipped are in db? - // Call only after remaining_padding_ has been set (for padded frames), or - // been cleared (for unpadded frames); and after all of the non-padding - // payload has been decoded. - size_t AvailablePadding(DecodeBuffer* db) const { - QUICHE_DCHECK(IsPaddable()) << frame_header(); - QUICHE_DCHECK_EQ(remaining_payload_, 0u); - return db->MinLengthRemaining(remaining_padding_); - } - - // Reduces remaining_payload_ by amount. To be called by a payload decoder - // after it has passed a variable length portion of the payload to the - // listener; remaining_payload_ will be automatically reduced when fixed - // size structures and padding, including the Pad Length field, are decoded. - void ConsumePayload(size_t amount) { - QUICHE_DCHECK_LE(amount, remaining_payload_); - remaining_payload_ -= amount; - } - - // Reads the Pad Length field into remaining_padding_, and appropriately sets - // remaining_payload_. When present, the Pad Length field is always the first - // field in the payload, which this method relies on so that the caller need - // not set remaining_payload_ before calling this method. - // If report_pad_length is true, calls the listener's OnPadLength method when - // it decodes the Pad Length field. - // Returns kDecodeDone if the decode buffer was not empty (i.e. because the - // field is only a single byte long, it can always be decoded if the buffer is - // not empty). - // Returns kDecodeError if the buffer is empty because the frame has no - // payload (i.e. payload_length() == 0). - // Returns kDecodeInProgress if the buffer is empty but the frame has a - // payload. - DecodeStatus ReadPadLength(DecodeBuffer* db, bool report_pad_length); - - // Skip the trailing padding bytes; only call once remaining_payload_==0. - // Returns true when the padding has been skipped. - // Does NOT check that the padding is all zeroes. - bool SkipPadding(DecodeBuffer* db); - - // Calls the listener's OnFrameSizeError method and returns kDecodeError. - DecodeStatus ReportFrameSizeError(); - - private: - friend class Http2FrameDecoder; - friend class test::FrameDecoderStatePeer; - - // Starts the decoding of a common frame header. Returns true if completed the - // decoding, false if the decode buffer didn't have enough data in it, in - // which case the decode buffer will have been drained and the caller should - // call ResumeDecodingFrameHeader when more data is available. This is called - // from Http2FrameDecoder, a friend class. - bool StartDecodingFrameHeader(DecodeBuffer* db) { - return structure_decoder_.Start(&frame_header_, db); - } - - // Resumes decoding the common frame header after the preceding call to - // StartDecodingFrameHeader returned false, as did any subsequent calls to - // ResumeDecodingFrameHeader. This is called from Http2FrameDecoder, - // a friend class. - bool ResumeDecodingFrameHeader(DecodeBuffer* db) { - return structure_decoder_.Resume(&frame_header_, db); - } - - // Clear any of the flags in the frame header that aren't set in valid_flags. - void RetainFlags(uint8_t valid_flags) { - frame_header_.RetainFlags(valid_flags); - } - - // Clear all of the flags in the frame header; for use with frame types that - // don't define any flags, such as WINDOW_UPDATE. - void ClearFlags() { frame_header_.flags = Http2FrameFlag(); } - - // Returns true if the type of frame being decoded can have padding. - bool IsPaddable() const { - return frame_header().type == Http2FrameType::DATA || - frame_header().type == Http2FrameType::HEADERS || - frame_header().type == Http2FrameType::PUSH_PROMISE; - } - - Http2FrameDecoderListener* listener_ = nullptr; - Http2FrameHeader frame_header_; - - // Number of bytes remaining to be decoded, if set; does not include the - // trailing padding once the length of padding has been determined. - // See ReadPadLength. - uint32_t remaining_payload_; - - // The amount of trailing padding after the payload that remains to be - // decoded. See ReadPadLength. - uint32_t remaining_padding_; - - // Generic decoder of structures, which takes care of buffering the needed - // bytes if the encoded structure is split across decode buffers. - Http2StructureDecoder structure_decoder_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_FRAME_DECODER_STATE_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.cc b/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.cc deleted file mode 100644 index e95f657930c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/frame_decoder_state_test_util.h" - -#include "http2/decoder/http2_structure_decoder_test_util.h" -#include "http2/http2_structures.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/random_decoder_test.h" - -namespace http2 { -namespace test { - -// static -void FrameDecoderStatePeer::Randomize(FrameDecoderState* p, Http2Random* rng) { - HTTP2_VLOG(1) << "FrameDecoderStatePeer::Randomize"; - ::http2::test::Randomize(&p->frame_header_, rng); - p->remaining_payload_ = rng->Rand32(); - p->remaining_padding_ = rng->Rand32(); - Http2StructureDecoderPeer::Randomize(&p->structure_decoder_, rng); -} - -// static -void FrameDecoderStatePeer::set_frame_header(const Http2FrameHeader& header, - FrameDecoderState* p) { - HTTP2_VLOG(1) << "FrameDecoderStatePeer::set_frame_header " << header; - p->frame_header_ = header; -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.h b/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.h deleted file mode 100644 index 8955cb7b3aa..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_ -#define QUICHE_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_ - -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "http2/tools/random_decoder_test.h" - -namespace http2 { -namespace test { - -class FrameDecoderStatePeer { - public: - // Randomizes (i.e. corrupts) the fields of the FrameDecoderState. - // PayloadDecoderBaseTest::StartDecoding calls this before passing the first - // decode buffer to the payload decoder, which increases the likelihood of - // detecting any use of prior states of the decoder on the decoding of - // future payloads. - static void Randomize(FrameDecoderState* p, Http2Random* rng); - - // Inject a frame header into the FrameDecoderState. - // PayloadDecoderBaseTest::StartDecoding calls this just after calling - // Randomize (above), to simulate a full frame decoder having just finished - // decoding the common frame header and then calling the appropriate payload - // decoder based on the frame type in that frame header. - static void set_frame_header(const Http2FrameHeader& header, - FrameDecoderState* p); -}; - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc deleted file mode 100644 index ec2034bb1c4..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc +++ /dev/null @@ -1,460 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/http2_frame_decoder.h" - -#include "http2/decoder/decode_status.h" -#include "http2/hpack/varint/hpack_varint_decoder.h" -#include "http2/http2_constants.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_flag_utils.h" -#include "http2/platform/api/http2_flags.h" -#include "common/platform/api/quiche_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, Http2FrameDecoder::State v) { - switch (v) { - case Http2FrameDecoder::State::kStartDecodingHeader: - return out << "kStartDecodingHeader"; - case Http2FrameDecoder::State::kResumeDecodingHeader: - return out << "kResumeDecodingHeader"; - case Http2FrameDecoder::State::kResumeDecodingPayload: - return out << "kResumeDecodingPayload"; - case Http2FrameDecoder::State::kDiscardPayload: - return out << "kDiscardPayload"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG(http2_bug_155_1) << "Http2FrameDecoder::State " << unknown; - return out << "Http2FrameDecoder::State(" << unknown << ")"; -} - -Http2FrameDecoder::Http2FrameDecoder(Http2FrameDecoderListener* listener) - : state_(State::kStartDecodingHeader), - maximum_payload_size_(Http2SettingsInfo::DefaultMaxFrameSize()) { - set_listener(listener); -} - -void Http2FrameDecoder::set_listener(Http2FrameDecoderListener* listener) { - if (listener == nullptr) { - listener = &no_op_listener_; - } - frame_decoder_state_.set_listener(listener); -} - -Http2FrameDecoderListener* Http2FrameDecoder::listener() const { - return frame_decoder_state_.listener(); -} - -DecodeStatus Http2FrameDecoder::DecodeFrame(DecodeBuffer* db) { - HTTP2_DVLOG(2) << "Http2FrameDecoder::DecodeFrame state=" << state_; - switch (state_) { - case State::kStartDecodingHeader: - if (frame_decoder_state_.StartDecodingFrameHeader(db)) { - return StartDecodingPayload(db); - } - state_ = State::kResumeDecodingHeader; - return DecodeStatus::kDecodeInProgress; - - case State::kResumeDecodingHeader: - if (frame_decoder_state_.ResumeDecodingFrameHeader(db)) { - return StartDecodingPayload(db); - } - return DecodeStatus::kDecodeInProgress; - - case State::kResumeDecodingPayload: - return ResumeDecodingPayload(db); - - case State::kDiscardPayload: - return DiscardPayload(db); - } - - QUICHE_NOTREACHED(); - return DecodeStatus::kDecodeError; -} - -size_t Http2FrameDecoder::remaining_payload() const { - return frame_decoder_state_.remaining_payload(); -} - -uint32_t Http2FrameDecoder::remaining_padding() const { - return frame_decoder_state_.remaining_padding(); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPayload(DecodeBuffer* db) { - const Http2FrameHeader& header = frame_header(); - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - if (!listener()->OnFrameHeader(header)) { - HTTP2_DVLOG(2) << "OnFrameHeader rejected the frame, will discard; header: " - << header; - state_ = State::kDiscardPayload; - frame_decoder_state_.InitializeRemainders(); - return DecodeStatus::kDecodeError; - } - - if (header.payload_length > maximum_payload_size_) { - HTTP2_DVLOG(2) << "Payload length is greater than allowed: " - << header.payload_length << " > " << maximum_payload_size_ - << "\n header: " << header; - state_ = State::kDiscardPayload; - frame_decoder_state_.InitializeRemainders(); - listener()->OnFrameSizeError(header); - return DecodeStatus::kDecodeError; - } - - // The decode buffer can extend across many frames. Make sure that the - // buffer we pass to the start method that is specific to the frame type - // does not exend beyond this frame. - DecodeBufferSubset subset(db, header.payload_length); - DecodeStatus status; - switch (header.type) { - case Http2FrameType::DATA: - status = StartDecodingDataPayload(&subset); - break; - - case Http2FrameType::HEADERS: - status = StartDecodingHeadersPayload(&subset); - break; - - case Http2FrameType::PRIORITY: - status = StartDecodingPriorityPayload(&subset); - break; - - case Http2FrameType::RST_STREAM: - status = StartDecodingRstStreamPayload(&subset); - break; - - case Http2FrameType::SETTINGS: - status = StartDecodingSettingsPayload(&subset); - break; - - case Http2FrameType::PUSH_PROMISE: - status = StartDecodingPushPromisePayload(&subset); - break; - - case Http2FrameType::PING: - status = StartDecodingPingPayload(&subset); - break; - - case Http2FrameType::GOAWAY: - status = StartDecodingGoAwayPayload(&subset); - break; - - case Http2FrameType::WINDOW_UPDATE: - status = StartDecodingWindowUpdatePayload(&subset); - break; - - case Http2FrameType::CONTINUATION: - status = StartDecodingContinuationPayload(&subset); - break; - - case Http2FrameType::ALTSVC: - status = StartDecodingAltSvcPayload(&subset); - break; - - case Http2FrameType::PRIORITY_UPDATE: - status = StartDecodingPriorityUpdatePayload(&subset); - break; - - default: - status = StartDecodingUnknownPayload(&subset); - break; - } - - if (status == DecodeStatus::kDecodeDone) { - state_ = State::kStartDecodingHeader; - return status; - } else if (status == DecodeStatus::kDecodeInProgress) { - state_ = State::kResumeDecodingPayload; - return status; - } else { - state_ = State::kDiscardPayload; - return status; - } -} - -DecodeStatus Http2FrameDecoder::ResumeDecodingPayload(DecodeBuffer* db) { - // The decode buffer can extend across many frames. Make sure that the - // buffer we pass to the start method that is specific to the frame type - // does not exend beyond this frame. - size_t remaining = frame_decoder_state_.remaining_total_payload(); - QUICHE_DCHECK_LE(remaining, frame_header().payload_length); - DecodeBufferSubset subset(db, remaining); - DecodeStatus status; - switch (frame_header().type) { - case Http2FrameType::DATA: - status = ResumeDecodingDataPayload(&subset); - break; - - case Http2FrameType::HEADERS: - status = ResumeDecodingHeadersPayload(&subset); - break; - - case Http2FrameType::PRIORITY: - status = ResumeDecodingPriorityPayload(&subset); - break; - - case Http2FrameType::RST_STREAM: - status = ResumeDecodingRstStreamPayload(&subset); - break; - - case Http2FrameType::SETTINGS: - status = ResumeDecodingSettingsPayload(&subset); - break; - - case Http2FrameType::PUSH_PROMISE: - status = ResumeDecodingPushPromisePayload(&subset); - break; - - case Http2FrameType::PING: - status = ResumeDecodingPingPayload(&subset); - break; - - case Http2FrameType::GOAWAY: - status = ResumeDecodingGoAwayPayload(&subset); - break; - - case Http2FrameType::WINDOW_UPDATE: - status = ResumeDecodingWindowUpdatePayload(&subset); - break; - - case Http2FrameType::CONTINUATION: - status = ResumeDecodingContinuationPayload(&subset); - break; - - case Http2FrameType::ALTSVC: - status = ResumeDecodingAltSvcPayload(&subset); - break; - - case Http2FrameType::PRIORITY_UPDATE: - status = ResumeDecodingPriorityUpdatePayload(&subset); - break; - - default: - status = ResumeDecodingUnknownPayload(&subset); - break; - } - - if (status == DecodeStatus::kDecodeDone) { - state_ = State::kStartDecodingHeader; - return status; - } else if (status == DecodeStatus::kDecodeInProgress) { - return status; - } else { - state_ = State::kDiscardPayload; - return status; - } -} - -// Clear any of the flags in the frame header that aren't set in valid_flags. -void Http2FrameDecoder::RetainFlags(uint8_t valid_flags) { - frame_decoder_state_.RetainFlags(valid_flags); -} - -// Clear all of the flags in the frame header; for use with frame types that -// don't define any flags, such as WINDOW_UPDATE. -void Http2FrameDecoder::ClearFlags() { - frame_decoder_state_.ClearFlags(); -} - -DecodeStatus Http2FrameDecoder::StartDecodingAltSvcPayload(DecodeBuffer* db) { - ClearFlags(); - return altsvc_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingAltSvcPayload(DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return altsvc_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingContinuationPayload( - DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_HEADERS); - return continuation_payload_decoder_.StartDecodingPayload( - &frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingContinuationPayload( - DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return continuation_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingDataPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED); - return data_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingDataPayload(DecodeBuffer* db) { - return data_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingGoAwayPayload(DecodeBuffer* db) { - ClearFlags(); - return goaway_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingGoAwayPayload(DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return goaway_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingHeadersPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY); - return headers_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingHeadersPayload(DecodeBuffer* db) { - QUICHE_DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(), - frame_header().payload_length); - return headers_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPingPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::ACK); - return ping_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingPingPayload(DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return ping_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPriorityPayload(DecodeBuffer* db) { - ClearFlags(); - return priority_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingPriorityPayload( - DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return priority_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPriorityUpdatePayload( - DecodeBuffer* db) { - ClearFlags(); - return priority_payload_update_decoder_.StartDecodingPayload( - &frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingPriorityUpdatePayload( - DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return priority_payload_update_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPushPromisePayload( - DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED); - return push_promise_payload_decoder_.StartDecodingPayload( - &frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingPushPromisePayload( - DecodeBuffer* db) { - QUICHE_DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(), - frame_header().payload_length); - return push_promise_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingRstStreamPayload( - DecodeBuffer* db) { - ClearFlags(); - return rst_stream_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingRstStreamPayload( - DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return rst_stream_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingSettingsPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::ACK); - return settings_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingSettingsPayload( - DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return settings_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingUnknownPayload(DecodeBuffer* db) { - // We don't known what type of frame this is, so we don't know which flags - // are valid, so we don't touch them. - return unknown_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingUnknownPayload(DecodeBuffer* db) { - // We don't known what type of frame this is, so we treat it as not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return unknown_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingWindowUpdatePayload( - DecodeBuffer* db) { - ClearFlags(); - return window_update_payload_decoder_.StartDecodingPayload( - &frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingWindowUpdatePayload( - DecodeBuffer* db) { - // The frame is not paddable. - QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return window_update_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::DiscardPayload(DecodeBuffer* db) { - HTTP2_DVLOG(2) << "remaining_payload=" - << frame_decoder_state_.remaining_payload_ - << "; remaining_padding=" - << frame_decoder_state_.remaining_padding_; - frame_decoder_state_.remaining_payload_ += - frame_decoder_state_.remaining_padding_; - frame_decoder_state_.remaining_padding_ = 0; - const size_t avail = frame_decoder_state_.AvailablePayload(db); - HTTP2_DVLOG(2) << "avail=" << avail; - if (avail > 0) { - frame_decoder_state_.ConsumePayload(avail); - db->AdvanceCursor(avail); - } - if (frame_decoder_state_.remaining_payload_ == 0) { - state_ = State::kStartDecodingHeader; - return DecodeStatus::kDecodeDone; - } - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h deleted file mode 100644 index 295a0b04c7f..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_ -#define QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_ - -// Http2FrameDecoder decodes the available input until it reaches the end of -// the input or it reaches the end of the first frame in the input. -// Note that Http2FrameDecoder does only minimal validation; for example, -// stream ids are not checked, nor is the sequence of frames such as -// CONTINUATION frame placement. -// -// Http2FrameDecoder enters state kError once it has called the listener's -// OnFrameSizeError or OnPaddingTooLong methods, and at this time has no -// provision for leaving that state. While the HTTP/2 spec (RFC7540) allows -// for some such errors to be considered as just stream errors in some cases, -// this implementation treats them all as connection errors. - -#include <stddef.h> - -#include <cstdint> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/altsvc_payload_decoder.h" -#include "http2/decoder/payload_decoders/continuation_payload_decoder.h" -#include "http2/decoder/payload_decoders/data_payload_decoder.h" -#include "http2/decoder/payload_decoders/goaway_payload_decoder.h" -#include "http2/decoder/payload_decoders/headers_payload_decoder.h" -#include "http2/decoder/payload_decoders/ping_payload_decoder.h" -#include "http2/decoder/payload_decoders/priority_payload_decoder.h" -#include "http2/decoder/payload_decoders/priority_update_payload_decoder.h" -#include "http2/decoder/payload_decoders/push_promise_payload_decoder.h" -#include "http2/decoder/payload_decoders/rst_stream_payload_decoder.h" -#include "http2/decoder/payload_decoders/settings_payload_decoder.h" -#include "http2/decoder/payload_decoders/unknown_payload_decoder.h" -#include "http2/decoder/payload_decoders/window_update_payload_decoder.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class Http2FrameDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE Http2FrameDecoder { - public: - explicit Http2FrameDecoder(Http2FrameDecoderListener* listener); - Http2FrameDecoder() : Http2FrameDecoder(nullptr) {} - - Http2FrameDecoder(const Http2FrameDecoder&) = delete; - Http2FrameDecoder& operator=(const Http2FrameDecoder&) = delete; - - // The decoder will call the listener's methods as it decodes a frame. - void set_listener(Http2FrameDecoderListener* listener); - Http2FrameDecoderListener* listener() const; - - // The decoder will reject frame's whose payload - // length field exceeds the maximum payload size. - void set_maximum_payload_size(size_t v) { maximum_payload_size_ = v; } - size_t maximum_payload_size() const { return maximum_payload_size_; } - - // Decodes the input up to the next frame boundary (i.e. at most one frame). - // - // Returns kDecodeDone if it decodes the final byte of a frame, OR if there - // is no input and it is awaiting the start of a new frame (e.g. if this - // is the first call to DecodeFrame, or if the previous call returned - // kDecodeDone). - // - // Returns kDecodeInProgress if it decodes all of the decode buffer, but has - // not reached the end of the frame. - // - // Returns kDecodeError if the frame's padding or length wasn't valid (i.e. if - // the decoder called either the listener's OnPaddingTooLong or - // OnFrameSizeError method). - // - // If the decode buffer contains the entirety of a frame payload or field, - // then the corresponding Http2FrameDecoderListener::On*Payload(), - // OnHpackFragment(), OnGoAwayOpaqueData(), or OnAltSvcValueData() method is - // guaranteed to be called exactly once, with the entire payload or field in a - // single chunk. - DecodeStatus DecodeFrame(DecodeBuffer* db); - - ////////////////////////////////////////////////////////////////////////////// - // Methods that support Http2FrameDecoderAdapter. - - // Is the remainder of the frame's payload being discarded? - bool IsDiscardingPayload() const { return state_ == State::kDiscardPayload; } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, excluding any trailing padding. This method must only be called - // after the frame header has been decoded AND DecodeFrame has returned - // kDecodeInProgress. - size_t remaining_payload() const; - - // Returns the number of bytes of trailing padding after the payload that - // remain to be decoded. This method must only be called if the frame type - // allows padding, and after the frame header has been decoded AND - // DecodeFrame has returned. Will return 0 if the Pad Length field has not - // yet been decoded. - uint32_t remaining_padding() const; - - private: - enum class State { - // Ready to start decoding a new frame's header. - kStartDecodingHeader, - // Was in state kStartDecodingHeader, but unable to read the entire frame - // header, so needs more input to complete decoding the header. - kResumeDecodingHeader, - - // Have decoded the frame header, and started decoding the available bytes - // of the frame's payload, but need more bytes to finish the job. - kResumeDecodingPayload, - - // Decoding of the most recently started frame resulted in an error: - // OnPaddingTooLong or OnFrameSizeError was called to indicate that the - // decoder detected a problem, or OnFrameHeader returned false, indicating - // that the listener detected a problem. Regardless of which, the decoder - // will stay in state kDiscardPayload until it has been passed the rest - // of the bytes of the frame's payload that it hasn't yet seen, after - // which it will be ready to decode another frame. - kDiscardPayload, - }; - - friend class test::Http2FrameDecoderPeer; - friend std::ostream& operator<<(std::ostream& out, State v); - - DecodeStatus StartDecodingPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPayload(DecodeBuffer* db); - DecodeStatus DiscardPayload(DecodeBuffer* db); - - const Http2FrameHeader& frame_header() const { - return frame_decoder_state_.frame_header(); - } - - // Clear any of the flags in the frame header that aren't set in valid_flags. - void RetainFlags(uint8_t valid_flags); - - // Clear all of the flags in the frame header; for use with frame types that - // don't define any flags, such as WINDOW_UPDATE. - void ClearFlags(); - - // These methods call the StartDecodingPayload() method of the frame type's - // payload decoder, after first clearing invalid flags in the header. The - // caller must ensure that the decode buffer does not extend beyond the - // end of the payload (handled by Http2FrameDecoder::StartDecodingPayload). - DecodeStatus StartDecodingAltSvcPayload(DecodeBuffer* db); - DecodeStatus StartDecodingContinuationPayload(DecodeBuffer* db); - DecodeStatus StartDecodingDataPayload(DecodeBuffer* db); - DecodeStatus StartDecodingGoAwayPayload(DecodeBuffer* db); - DecodeStatus StartDecodingHeadersPayload(DecodeBuffer* db); - DecodeStatus StartDecodingPingPayload(DecodeBuffer* db); - DecodeStatus StartDecodingPriorityPayload(DecodeBuffer* db); - DecodeStatus StartDecodingPriorityUpdatePayload(DecodeBuffer* db); - DecodeStatus StartDecodingPushPromisePayload(DecodeBuffer* db); - DecodeStatus StartDecodingRstStreamPayload(DecodeBuffer* db); - DecodeStatus StartDecodingSettingsPayload(DecodeBuffer* db); - DecodeStatus StartDecodingUnknownPayload(DecodeBuffer* db); - DecodeStatus StartDecodingWindowUpdatePayload(DecodeBuffer* db); - - // These methods call the ResumeDecodingPayload() method of the frame type's - // payload decoder; they are called only if the preceding call to the - // corresponding Start method (above) returned kDecodeInProgress, as did any - // subsequent calls to the resume method. - // Unlike the Start methods, the decode buffer may extend beyond the - // end of the payload, so the method will create a DecodeBufferSubset - // before calling the ResumeDecodingPayload method of the frame type's - // payload decoder. - DecodeStatus ResumeDecodingAltSvcPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingContinuationPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingDataPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingGoAwayPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingHeadersPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPingPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPriorityPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPriorityUpdatePayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPushPromisePayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingRstStreamPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingSettingsPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingUnknownPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingWindowUpdatePayload(DecodeBuffer* db); - - FrameDecoderState frame_decoder_state_; - - // We only need one payload decoder at a time, so they share the same storage. - union { - AltSvcPayloadDecoder altsvc_payload_decoder_; - ContinuationPayloadDecoder continuation_payload_decoder_; - DataPayloadDecoder data_payload_decoder_; - GoAwayPayloadDecoder goaway_payload_decoder_; - HeadersPayloadDecoder headers_payload_decoder_; - PingPayloadDecoder ping_payload_decoder_; - PriorityPayloadDecoder priority_payload_decoder_; - PriorityUpdatePayloadDecoder priority_payload_update_decoder_; - PushPromisePayloadDecoder push_promise_payload_decoder_; - RstStreamPayloadDecoder rst_stream_payload_decoder_; - SettingsPayloadDecoder settings_payload_decoder_; - UnknownPayloadDecoder unknown_payload_decoder_; - WindowUpdatePayloadDecoder window_update_payload_decoder_; - }; - - State state_; - size_t maximum_payload_size_; - - // Listener used whenever caller passes nullptr to set_listener. - Http2FrameDecoderNoOpListener no_op_listener_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.cc deleted file mode 100644 index 452f0594047..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.cc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/http2_frame_decoder_listener.h" - -namespace http2 { - -bool Http2FrameDecoderNoOpListener::OnFrameHeader( - const Http2FrameHeader& /*header*/) { - return true; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h deleted file mode 100644 index 9bb16889060..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_ -#define QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_ - -// Http2FrameDecoderListener is the interface which the HTTP/2 decoder uses -// to report the decoded frames to a listener. -// -// The general design is to assume that the listener will copy the data it needs -// (e.g. frame headers) and will keep track of the implicit state of the -// decoding process (i.e. the decoder maintains just the information it needs in -// order to perform the decoding). Therefore, the parameters are just those with -// (potentially) new data, not previously provided info about the current frame. -// -// The calls are described as if they are made in quick succession, i.e. one -// after another, but of course the decoder needs input to decode, and the -// decoder will only call the listener once the necessary input has been -// provided. For example: OnDataStart can only be called once the 9 bytes of -// of an HTTP/2 common frame header have been received. The decoder will call -// the listener methods as soon as possible to avoid almost all buffering. -// -// The listener interface is designed so that it is possible to exactly -// reconstruct the serialized frames, with the exception of reserved bits, -// including in the frame header's flags and stream_id fields, which will have -// been cleared before the methods below are called. - -#include <stddef.h> - -#include <cstdint> -#include <type_traits> - -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" - -namespace http2 { - -// TODO(jamessynge): Consider sorting the methods by frequency of call, if that -// helps at all. -class Http2FrameDecoderListener { - public: - Http2FrameDecoderListener() {} - virtual ~Http2FrameDecoderListener() {} - - // Called once the common frame header has been decoded for any frame, and - // before any of the methods below, which will also be called. This method is - // included in this interface only for the purpose of supporting SpdyFramer - // semantics via an adapter. This is the only method that has a non-void - // return type, and this is just so that Http2FrameDecoderAdapter (called - // from SpdyFramer) can more readily pass existing tests that expect decoding - // to stop if the headers alone indicate an error. Return false to stop - // decoding just after decoding the header, else return true to continue - // decoding. - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - virtual bool OnFrameHeader(const Http2FrameHeader& header) = 0; - - ////////////////////////////////////////////////////////////////////////////// - - // Called once the common frame header has been decoded for a DATA frame, - // before examining the frame's payload, after which: - // OnPadLength will be called if header.IsPadded() is true, i.e. if the - // PADDED flag is set; - // OnDataPayload will be called as the non-padding portion of the payload - // is available until all of it has been provided; - // OnPadding will be called if the frame is padded AND the Pad Length field - // is greater than zero; - // OnDataEnd will be called last. If the frame is unpadded and has no - // payload, then this will be called immediately after OnDataStart. - virtual void OnDataStart(const Http2FrameHeader& header) = 0; - - // Called when the next non-padding portion of a DATA frame's payload is - // received. - // |data| The start of |len| bytes of data. - // |len| The length of the data buffer. Maybe zero in some cases, which does - // not mean anything special. - virtual void OnDataPayload(const char* data, size_t len) = 0; - - // Called after an entire DATA frame has been received. - // If header.IsEndStream() == true, this is the last data for the stream. - virtual void OnDataEnd() = 0; - - // Called once the common frame header has been decoded for a HEADERS frame, - // before examining the frame's payload, after which: - // OnPadLength will be called if header.IsPadded() is true, i.e. if the - // PADDED flag is set; - // OnHeadersPriority will be called if header.HasPriority() is true, i.e. if - // the frame has the PRIORITY flag; - // OnHpackFragment as the remainder of the non-padding payload is available - // until all if has been provided; - // OnPadding will be called if the frame is padded AND the Pad Length field - // is greater than zero; - // OnHeadersEnd will be called last; If the frame is unpadded and has no - // payload, then this will be called immediately after OnHeadersStart; - // OnHeadersEnd indicates the end of the HPACK block only if the frame - // header had the END_HEADERS flag set, else the END_HEADERS should be - // looked for on a subsequent CONTINUATION frame. - virtual void OnHeadersStart(const Http2FrameHeader& header) = 0; - - // Called when a HEADERS frame is received with the PRIORITY flag set and - // the priority fields have been decoded. - virtual void OnHeadersPriority( - const Http2PriorityFields& priority_fields) = 0; - - // Called when a fragment (i.e. some or all of an HPACK Block) is received; - // this may be part of a HEADERS, PUSH_PROMISE or CONTINUATION frame. - // |data| The start of |len| bytes of data. - // |len| The length of the data buffer. Maybe zero in some cases, which does - // not mean anything special, except that it simplified the decoder. - virtual void OnHpackFragment(const char* data, size_t len) = 0; - - // Called after an entire HEADERS frame has been received. The frame is the - // end of the HEADERS if the END_HEADERS flag is set; else there should be - // CONTINUATION frames after this frame. - virtual void OnHeadersEnd() = 0; - - // Called when an entire PRIORITY frame has been decoded. - virtual void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority_fields) = 0; - - // Called once the common frame header has been decoded for a CONTINUATION - // frame, before examining the frame's payload, after which: - // OnHpackFragment as the frame's payload is available until all of it - // has been provided; - // OnContinuationEnd will be called last; If the frame has no payload, - // then this will be called immediately after OnContinuationStart; - // the HPACK block is at an end if and only if the frame header passed - // to OnContinuationStart had the END_HEADERS flag set. - virtual void OnContinuationStart(const Http2FrameHeader& header) = 0; - - // Called after an entire CONTINUATION frame has been received. The frame is - // the end of the HEADERS if the END_HEADERS flag is set. - virtual void OnContinuationEnd() = 0; - - // Called when Pad Length field has been read. Applies to DATA and HEADERS - // frames. For PUSH_PROMISE frames, the Pad Length + 1 is provided in the - // OnPushPromiseStart call as total_padding_length. - virtual void OnPadLength(size_t pad_length) = 0; - - // Called when padding is skipped over. - virtual void OnPadding(const char* padding, size_t skipped_length) = 0; - - // Called when an entire RST_STREAM frame has been decoded. - // This is the only callback for RST_STREAM frames. - virtual void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) = 0; - - // Called once the common frame header has been decoded for a SETTINGS frame - // without the ACK flag, before examining the frame's payload, after which: - // OnSetting will be called in turn for each pair of settings parameter and - // value found in the payload; - // OnSettingsEnd will be called last; If the frame has no payload, - // then this will be called immediately after OnSettingsStart. - // The frame header is passed so that the caller can check the stream_id, - // which should be zero, but that hasn't been checked by the decoder. - virtual void OnSettingsStart(const Http2FrameHeader& header) = 0; - - // Called for each setting parameter and value within a SETTINGS frame. - virtual void OnSetting(const Http2SettingFields& setting_fields) = 0; - - // Called after parsing the complete payload of SETTINGS frame (non-ACK). - virtual void OnSettingsEnd() = 0; - - // Called when an entire SETTINGS frame, with the ACK flag, has been decoded. - virtual void OnSettingsAck(const Http2FrameHeader& header) = 0; - - // Called just before starting to process the HPACK block of a PUSH_PROMISE - // frame. The Pad Length field has already been decoded at this point, so - // OnPadLength will not be called; note that total_padding_length is Pad - // Length + 1. After OnPushPromiseStart: - // OnHpackFragment as the remainder of the non-padding payload is available - // until all if has been provided; - // OnPadding will be called if the frame is padded AND the Pad Length field - // is greater than zero (i.e. total_padding_length > 1); - // OnPushPromiseEnd will be called last; If the frame is unpadded and has no - // payload, then this will be called immediately after OnPushPromiseStart. - virtual void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) = 0; - - // Called after all of the HPACK block fragment and padding of a PUSH_PROMISE - // has been decoded and delivered to the listener. This call indicates the end - // of the HPACK block if and only if the frame header had the END_HEADERS flag - // set (i.e. header.IsEndHeaders() is true); otherwise the next block must be - // a CONTINUATION frame with the same stream id (not the same promised stream - // id). - virtual void OnPushPromiseEnd() = 0; - - // Called when an entire PING frame, without the ACK flag, has been decoded. - virtual void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) = 0; - - // Called when an entire PING frame, with the ACK flag, has been decoded. - virtual void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) = 0; - - // Called after parsing a GOAWAY frame's header and fixed size fields, after - // which: - // OnGoAwayOpaqueData will be called as opaque data of the payload becomes - // available to the decoder, until all of it has been provided to the - // listener; - // OnGoAwayEnd will be called last, after all the opaque data has been - // provided to the listener; if there is no opaque data, then OnGoAwayEnd - // will be called immediately after OnGoAwayStart. - virtual void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) = 0; - - // Called when the next portion of a GOAWAY frame's payload is received. - // |data| The start of |len| bytes of opaque data. - // |len| The length of the opaque data buffer. Maybe zero in some cases, - // which does not mean anything special. - virtual void OnGoAwayOpaqueData(const char* data, size_t len) = 0; - - // Called after finishing decoding all of a GOAWAY frame. - virtual void OnGoAwayEnd() = 0; - - // Called when an entire WINDOW_UPDATE frame has been decoded. The - // window_size_increment is required to be non-zero, but that has not been - // checked. If header.stream_id==0, the connection's flow control window is - // being increased, else the specified stream's flow control is being - // increased. - virtual void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t window_size_increment) = 0; - - // Called when an ALTSVC frame header and origin length have been parsed. - // Either or both lengths may be zero. After OnAltSvcStart: - // OnAltSvcOriginData will be called until all of the (optional) Origin - // has been provided; - // OnAltSvcValueData will be called until all of the Alt-Svc-Field-Value - // has been provided; - // OnAltSvcEnd will called last, after all of the origin and - // Alt-Svc-Field-Value have been delivered to the listener. - virtual void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) = 0; - - // Called when decoding the (optional) origin of an ALTSVC; - // the field is uninterpreted. - virtual void OnAltSvcOriginData(const char* data, size_t len) = 0; - - // Called when decoding the Alt-Svc-Field-Value of an ALTSVC; - // the field is uninterpreted. - virtual void OnAltSvcValueData(const char* data, size_t len) = 0; - - // Called after decoding all of a ALTSVC frame and providing to the listener - // via the above methods. - virtual void OnAltSvcEnd() = 0; - - // Called when an PRIORITY_UPDATE frame header and Prioritized Stream ID have - // been parsed. Afterwards: - // OnPriorityUpdatePayload will be called each time a portion of the - // Priority Field Value field is available until all of it has been - // provided; - // OnPriorityUpdateEnd will be called last. If the frame has an empty - // Priority Field Value, then this will be called immediately after - // OnPriorityUpdateStart. - virtual void OnPriorityUpdateStart( - const Http2FrameHeader& header, - const Http2PriorityUpdateFields& priority_update) = 0; - - // Called when the next portion of a PRIORITY_UPDATE frame's Priority Field - // Value field is received. - // |data| The start of |len| bytes of data. - // |len| The length of the data buffer. May be zero in some cases, which does - // not mean anything special. - virtual void OnPriorityUpdatePayload(const char* data, size_t len) = 0; - - // Called after an entire PRIORITY_UPDATE frame has been received. - virtual void OnPriorityUpdateEnd() = 0; - - // Called when the common frame header has been decoded, but the frame type - // is unknown, after which: - // OnUnknownPayload is called as the payload of the frame is provided to the - // decoder, until all of the payload has been decoded; - // OnUnknownEnd will called last, after the entire frame of the unknown type - // has been decoded and provided to the listener. - virtual void OnUnknownStart(const Http2FrameHeader& header) = 0; - - // Called when the payload of an unknown frame type is received. - // |data| A buffer containing the data received. - // |len| The length of the data buffer. - virtual void OnUnknownPayload(const char* data, size_t len) = 0; - - // Called after decoding all of the payload of an unknown frame type. - virtual void OnUnknownEnd() = 0; - - ////////////////////////////////////////////////////////////////////////////// - // Below here are events indicating a problem has been detected during - // decoding (i.e. the received frames are malformed in some way). - - // Padding field (uint8) has a value that is too large (i.e. the amount of - // padding is greater than the remainder of the payload that isn't required). - // From RFC Section 6.1, DATA: - // If the length of the padding is the length of the frame payload or - // greater, the recipient MUST treat this as a connection error - // (Section 5.4.1) of type PROTOCOL_ERROR. - // The same is true for HEADERS and PUSH_PROMISE. - virtual void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) = 0; - - // Frame size error. Depending upon the effected frame, this may or may not - // require terminating the connection, though that is probably the best thing - // to do. - // From RFC Section 4.2, Frame Size: - // An endpoint MUST send an error code of FRAME_SIZE_ERROR if a frame - // exceeds the size defined in SETTINGS_MAX_FRAME_SIZE, exceeds any limit - // defined for the frame type, or is too small to contain mandatory frame - // data. A frame size error in a frame that could alter the state of the - // the entire connection MUST be treated as a connection error - // (Section 5.4.1); this includes any frame carrying a header block - // (Section 4.3) (that is, HEADERS, PUSH_PROMISE, and CONTINUATION), - // SETTINGS, and any frame with a stream identifier of 0. - virtual void OnFrameSizeError(const Http2FrameHeader& header) = 0; -}; - -// Do nothing for each call. Useful for ignoring a frame that is invalid. -class Http2FrameDecoderNoOpListener : public Http2FrameDecoderListener { - public: - Http2FrameDecoderNoOpListener() {} - ~Http2FrameDecoderNoOpListener() override {} - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - bool OnFrameHeader(const Http2FrameHeader& header) override; - - void OnDataStart(const Http2FrameHeader& /*header*/) override {} - void OnDataPayload(const char* /*data*/, size_t /*len*/) override {} - void OnDataEnd() override {} - void OnHeadersStart(const Http2FrameHeader& /*header*/) override {} - void OnHeadersPriority(const Http2PriorityFields& /*priority*/) override {} - void OnHpackFragment(const char* /*data*/, size_t /*len*/) override {} - void OnHeadersEnd() override {} - void OnPriorityFrame(const Http2FrameHeader& /*header*/, - const Http2PriorityFields& /*priority*/) override {} - void OnContinuationStart(const Http2FrameHeader& /*header*/) override {} - void OnContinuationEnd() override {} - void OnPadLength(size_t /*trailing_length*/) override {} - void OnPadding(const char* /*padding*/, size_t /*skipped_length*/) override {} - void OnRstStream(const Http2FrameHeader& /*header*/, - Http2ErrorCode /*error_code*/) override {} - void OnSettingsStart(const Http2FrameHeader& /*header*/) override {} - void OnSetting(const Http2SettingFields& /*setting_fields*/) override {} - void OnSettingsEnd() override {} - void OnSettingsAck(const Http2FrameHeader& /*header*/) override {} - void OnPushPromiseStart(const Http2FrameHeader& /*header*/, - const Http2PushPromiseFields& /*promise*/, - size_t /*total_padding_length*/) override {} - void OnPushPromiseEnd() override {} - void OnPing(const Http2FrameHeader& /*header*/, - const Http2PingFields& /*ping*/) override {} - void OnPingAck(const Http2FrameHeader& /*header*/, - const Http2PingFields& /*ping*/) override {} - void OnGoAwayStart(const Http2FrameHeader& /*header*/, - const Http2GoAwayFields& /*goaway*/) override {} - void OnGoAwayOpaqueData(const char* /*data*/, size_t /*len*/) override {} - void OnGoAwayEnd() override {} - void OnWindowUpdate(const Http2FrameHeader& /*header*/, - uint32_t /*increment*/) override {} - void OnAltSvcStart(const Http2FrameHeader& /*header*/, - size_t /*origin_length*/, - size_t /*value_length*/) override {} - void OnAltSvcOriginData(const char* /*data*/, size_t /*len*/) override {} - void OnAltSvcValueData(const char* /*data*/, size_t /*len*/) override {} - void OnAltSvcEnd() override {} - void OnPriorityUpdateStart( - const Http2FrameHeader& /*header*/, - const Http2PriorityUpdateFields& /*priority_update*/) override {} - void OnPriorityUpdatePayload(const char* /*data*/, size_t /*len*/) override {} - void OnPriorityUpdateEnd() override {} - void OnUnknownStart(const Http2FrameHeader& /*header*/) override {} - void OnUnknownPayload(const char* /*data*/, size_t /*len*/) override {} - void OnUnknownEnd() override {} - void OnPaddingTooLong(const Http2FrameHeader& /*header*/, - size_t /*missing_length*/) override {} - void OnFrameSizeError(const Http2FrameHeader& /*header*/) override {} -}; - -static_assert(!std::is_abstract<Http2FrameDecoderNoOpListener>(), - "Http2FrameDecoderNoOpListener ought to be concrete."); - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.cc deleted file mode 100644 index ddd0064ac6b..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.cc +++ /dev/null @@ -1,530 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/http2_frame_decoder_listener_test_util.h" - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { - -FailingHttp2FrameDecoderListener::FailingHttp2FrameDecoderListener() = default; -FailingHttp2FrameDecoderListener::~FailingHttp2FrameDecoderListener() = default; - -bool FailingHttp2FrameDecoderListener::OnFrameHeader( - const Http2FrameHeader& header) { - ADD_FAILURE() << "OnFrameHeader: " << header; - return false; -} - -void FailingHttp2FrameDecoderListener::OnDataStart( - const Http2FrameHeader& header) { - FAIL() << "OnDataStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnDataPayload(const char* /*data*/, - size_t len) { - FAIL() << "OnDataPayload: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnDataEnd() { - FAIL() << "OnDataEnd"; -} - -void FailingHttp2FrameDecoderListener::OnHeadersStart( - const Http2FrameHeader& header) { - FAIL() << "OnHeadersStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnHeadersPriority( - const Http2PriorityFields& priority) { - FAIL() << "OnHeadersPriority: " << priority; -} - -void FailingHttp2FrameDecoderListener::OnHpackFragment(const char* /*data*/, - size_t len) { - FAIL() << "OnHpackFragment: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnHeadersEnd() { - FAIL() << "OnHeadersEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPriorityFrame( - const Http2FrameHeader& header, - const Http2PriorityFields& priority) { - FAIL() << "OnPriorityFrame: " << header << "; priority: " << priority; -} - -void FailingHttp2FrameDecoderListener::OnContinuationStart( - const Http2FrameHeader& header) { - FAIL() << "OnContinuationStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnContinuationEnd() { - FAIL() << "OnContinuationEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPadLength(size_t trailing_length) { - FAIL() << "OnPadLength: trailing_length=" << trailing_length; -} - -void FailingHttp2FrameDecoderListener::OnPadding(const char* /*padding*/, - size_t skipped_length) { - FAIL() << "OnPadding: skipped_length=" << skipped_length; -} - -void FailingHttp2FrameDecoderListener::OnRstStream( - const Http2FrameHeader& header, - Http2ErrorCode error_code) { - FAIL() << "OnRstStream: " << header << "; code=" << error_code; -} - -void FailingHttp2FrameDecoderListener::OnSettingsStart( - const Http2FrameHeader& header) { - FAIL() << "OnSettingsStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnSetting( - const Http2SettingFields& setting_fields) { - FAIL() << "OnSetting: " << setting_fields; -} - -void FailingHttp2FrameDecoderListener::OnSettingsEnd() { - FAIL() << "OnSettingsEnd"; -} - -void FailingHttp2FrameDecoderListener::OnSettingsAck( - const Http2FrameHeader& header) { - FAIL() << "OnSettingsAck: " << header; -} - -void FailingHttp2FrameDecoderListener::OnPushPromiseStart( - const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) { - FAIL() << "OnPushPromiseStart: " << header << "; promise: " << promise - << "; total_padding_length: " << total_padding_length; -} - -void FailingHttp2FrameDecoderListener::OnPushPromiseEnd() { - FAIL() << "OnPushPromiseEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) { - FAIL() << "OnPing: " << header << "; ping: " << ping; -} - -void FailingHttp2FrameDecoderListener::OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) { - FAIL() << "OnPingAck: " << header << "; ping: " << ping; -} - -void FailingHttp2FrameDecoderListener::OnGoAwayStart( - const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) { - FAIL() << "OnGoAwayStart: " << header << "; goaway: " << goaway; -} - -void FailingHttp2FrameDecoderListener::OnGoAwayOpaqueData(const char* /*data*/, - size_t len) { - FAIL() << "OnGoAwayOpaqueData: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnGoAwayEnd() { - FAIL() << "OnGoAwayEnd"; -} - -void FailingHttp2FrameDecoderListener::OnWindowUpdate( - const Http2FrameHeader& header, - uint32_t increment) { - FAIL() << "OnWindowUpdate: " << header << "; increment=" << increment; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcStart( - const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) { - FAIL() << "OnAltSvcStart: " << header << "; origin_length: " << origin_length - << "; value_length: " << value_length; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcOriginData(const char* /*data*/, - size_t len) { - FAIL() << "OnAltSvcOriginData: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcValueData(const char* /*data*/, - size_t len) { - FAIL() << "OnAltSvcValueData: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcEnd() { - FAIL() << "OnAltSvcEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPriorityUpdateStart( - const Http2FrameHeader& header, - const Http2PriorityUpdateFields& priority_update) { - FAIL() << "OnPriorityUpdateStart: " << header << "; prioritized_stream_id: " - << priority_update.prioritized_stream_id; -} - -void FailingHttp2FrameDecoderListener::OnPriorityUpdatePayload( - const char* /*data*/, - size_t len) { - FAIL() << "OnPriorityUpdatePayload: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnPriorityUpdateEnd() { - FAIL() << "OnPriorityUpdateEnd"; -} - -void FailingHttp2FrameDecoderListener::OnUnknownStart( - const Http2FrameHeader& header) { - FAIL() << "OnUnknownStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnUnknownPayload(const char* /*data*/, - size_t len) { - FAIL() << "OnUnknownPayload: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnUnknownEnd() { - FAIL() << "OnUnknownEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPaddingTooLong( - const Http2FrameHeader& header, - size_t missing_length) { - FAIL() << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; -} - -void FailingHttp2FrameDecoderListener::OnFrameSizeError( - const Http2FrameHeader& header) { - FAIL() << "OnFrameSizeError: " << header; -} - -LoggingHttp2FrameDecoderListener::LoggingHttp2FrameDecoderListener() - : wrapped_(nullptr) {} -LoggingHttp2FrameDecoderListener::LoggingHttp2FrameDecoderListener( - Http2FrameDecoderListener* wrapped) - : wrapped_(wrapped) {} -LoggingHttp2FrameDecoderListener::~LoggingHttp2FrameDecoderListener() = default; - -bool LoggingHttp2FrameDecoderListener::OnFrameHeader( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnFrameHeader: " << header; - if (wrapped_ != nullptr) { - return wrapped_->OnFrameHeader(header); - } - return true; -} - -void LoggingHttp2FrameDecoderListener::OnDataStart( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnDataStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnDataStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnDataPayload(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnDataPayload: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnDataPayload(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnDataEnd() { - HTTP2_VLOG(1) << "OnDataEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnDataEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnHeadersStart( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnHeadersStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnHeadersStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnHeadersPriority( - const Http2PriorityFields& priority) { - HTTP2_VLOG(1) << "OnHeadersPriority: " << priority; - if (wrapped_ != nullptr) { - wrapped_->OnHeadersPriority(priority); - } -} - -void LoggingHttp2FrameDecoderListener::OnHpackFragment(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnHpackFragment: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnHpackFragment(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnHeadersEnd() { - HTTP2_VLOG(1) << "OnHeadersEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnHeadersEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPriorityFrame( - const Http2FrameHeader& header, - const Http2PriorityFields& priority) { - HTTP2_VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority; - if (wrapped_ != nullptr) { - wrapped_->OnPriorityFrame(header, priority); - } -} - -void LoggingHttp2FrameDecoderListener::OnContinuationStart( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnContinuationStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnContinuationStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnContinuationEnd() { - HTTP2_VLOG(1) << "OnContinuationEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnContinuationEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPadLength(size_t trailing_length) { - HTTP2_VLOG(1) << "OnPadLength: trailing_length=" << trailing_length; - if (wrapped_ != nullptr) { - wrapped_->OnPadLength(trailing_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnPadding(const char* padding, - size_t skipped_length) { - HTTP2_VLOG(1) << "OnPadding: skipped_length=" << skipped_length; - if (wrapped_ != nullptr) { - wrapped_->OnPadding(padding, skipped_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnRstStream( - const Http2FrameHeader& header, - Http2ErrorCode error_code) { - HTTP2_VLOG(1) << "OnRstStream: " << header << "; code=" << error_code; - if (wrapped_ != nullptr) { - wrapped_->OnRstStream(header, error_code); - } -} - -void LoggingHttp2FrameDecoderListener::OnSettingsStart( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnSettingsStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnSettingsStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnSetting( - const Http2SettingFields& setting_fields) { - HTTP2_VLOG(1) << "OnSetting: " << setting_fields; - if (wrapped_ != nullptr) { - wrapped_->OnSetting(setting_fields); - } -} - -void LoggingHttp2FrameDecoderListener::OnSettingsEnd() { - HTTP2_VLOG(1) << "OnSettingsEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnSettingsEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnSettingsAck( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnSettingsAck: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnSettingsAck(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnPushPromiseStart( - const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) { - HTTP2_VLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise - << "; total_padding_length: " << total_padding_length; - if (wrapped_ != nullptr) { - wrapped_->OnPushPromiseStart(header, promise, total_padding_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnPushPromiseEnd() { - HTTP2_VLOG(1) << "OnPushPromiseEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnPushPromiseEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) { - HTTP2_VLOG(1) << "OnPing: " << header << "; ping: " << ping; - if (wrapped_ != nullptr) { - wrapped_->OnPing(header, ping); - } -} - -void LoggingHttp2FrameDecoderListener::OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) { - HTTP2_VLOG(1) << "OnPingAck: " << header << "; ping: " << ping; - if (wrapped_ != nullptr) { - wrapped_->OnPingAck(header, ping); - } -} - -void LoggingHttp2FrameDecoderListener::OnGoAwayStart( - const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) { - HTTP2_VLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway; - if (wrapped_ != nullptr) { - wrapped_->OnGoAwayStart(header, goaway); - } -} - -void LoggingHttp2FrameDecoderListener::OnGoAwayOpaqueData(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnGoAwayOpaqueData: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnGoAwayOpaqueData(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnGoAwayEnd() { - HTTP2_VLOG(1) << "OnGoAwayEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnGoAwayEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnWindowUpdate( - const Http2FrameHeader& header, - uint32_t increment) { - HTTP2_VLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment; - if (wrapped_ != nullptr) { - wrapped_->OnWindowUpdate(header, increment); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcStart( - const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) { - HTTP2_VLOG(1) << "OnAltSvcStart: " << header - << "; origin_length: " << origin_length - << "; value_length: " << value_length; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcStart(header, origin_length, value_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcOriginData(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnAltSvcOriginData: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcOriginData(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcValueData(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnAltSvcValueData: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcValueData(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcEnd() { - HTTP2_VLOG(1) << "OnAltSvcEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPriorityUpdateStart( - const Http2FrameHeader& header, - const Http2PriorityUpdateFields& priority_update) { - HTTP2_VLOG(1) << "OnPriorityUpdateStart"; - if (wrapped_ != nullptr) { - wrapped_->OnPriorityUpdateStart(header, priority_update); - } -} - -void LoggingHttp2FrameDecoderListener::OnPriorityUpdatePayload(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnPriorityUpdatePayload"; - if (wrapped_ != nullptr) { - wrapped_->OnPriorityUpdatePayload(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnPriorityUpdateEnd() { - HTTP2_VLOG(1) << "OnPriorityUpdateEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnPriorityUpdateEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnUnknownStart( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnUnknownStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnUnknownStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnUnknownPayload(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnUnknownPayload: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnUnknownPayload(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnUnknownEnd() { - HTTP2_VLOG(1) << "OnUnknownEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnUnknownEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPaddingTooLong( - const Http2FrameHeader& header, - size_t missing_length) { - HTTP2_VLOG(1) << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; - if (wrapped_ != nullptr) { - wrapped_->OnPaddingTooLong(header, missing_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnFrameSizeError( - const Http2FrameHeader& header) { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnFrameSizeError(header); - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.h b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.h deleted file mode 100644 index e7483272b3d..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_ -#define QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_ - -#include <stddef.h> - -#include <cstdint> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" - -namespace http2 { - -// Fail if any of the methods are called. Allows a test to override only the -// expected calls. -class FailingHttp2FrameDecoderListener : public Http2FrameDecoderListener { - public: - FailingHttp2FrameDecoderListener(); - ~FailingHttp2FrameDecoderListener() override; - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - bool OnFrameHeader(const Http2FrameHeader& header) override; - void OnDataStart(const Http2FrameHeader& header) override; - void OnDataPayload(const char* data, size_t len) override; - void OnDataEnd() override; - void OnHeadersStart(const Http2FrameHeader& header) override; - void OnHeadersPriority(const Http2PriorityFields& priority) override; - void OnHpackFragment(const char* data, size_t len) override; - void OnHeadersEnd() override; - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) override; - void OnContinuationStart(const Http2FrameHeader& header) override; - void OnContinuationEnd() override; - void OnPadLength(size_t trailing_length) override; - void OnPadding(const char* padding, size_t skipped_length) override; - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override; - void OnSettingsStart(const Http2FrameHeader& header) override; - void OnSetting(const Http2SettingFields& setting_fields) override; - void OnSettingsEnd() override; - void OnSettingsAck(const Http2FrameHeader& header) override; - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override; - void OnPushPromiseEnd() override; - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override; - void OnGoAwayOpaqueData(const char* data, size_t len) override; - void OnGoAwayEnd() override; - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) override; - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override; - void OnAltSvcOriginData(const char* data, size_t len) override; - void OnAltSvcValueData(const char* data, size_t len) override; - void OnAltSvcEnd() override; - void OnPriorityUpdateStart( - const Http2FrameHeader& header, - const Http2PriorityUpdateFields& priority_update) override; - void OnPriorityUpdatePayload(const char* data, size_t len) override; - void OnPriorityUpdateEnd() override; - void OnUnknownStart(const Http2FrameHeader& header) override; - void OnUnknownPayload(const char* data, size_t len) override; - void OnUnknownEnd() override; - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override; - void OnFrameSizeError(const Http2FrameHeader& header) override; - - private: - void EnsureNotAbstract() { FailingHttp2FrameDecoderListener instance; } -}; - -// HTTP2_VLOG's all the calls it receives, and forwards those calls to an -// optional listener. -class LoggingHttp2FrameDecoderListener : public Http2FrameDecoderListener { - public: - LoggingHttp2FrameDecoderListener(); - explicit LoggingHttp2FrameDecoderListener(Http2FrameDecoderListener* wrapped); - ~LoggingHttp2FrameDecoderListener() override; - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - bool OnFrameHeader(const Http2FrameHeader& header) override; - void OnDataStart(const Http2FrameHeader& header) override; - void OnDataPayload(const char* data, size_t len) override; - void OnDataEnd() override; - void OnHeadersStart(const Http2FrameHeader& header) override; - void OnHeadersPriority(const Http2PriorityFields& priority) override; - void OnHpackFragment(const char* data, size_t len) override; - void OnHeadersEnd() override; - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) override; - void OnContinuationStart(const Http2FrameHeader& header) override; - void OnContinuationEnd() override; - void OnPadLength(size_t trailing_length) override; - void OnPadding(const char* padding, size_t skipped_length) override; - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override; - void OnSettingsStart(const Http2FrameHeader& header) override; - void OnSetting(const Http2SettingFields& setting_fields) override; - void OnSettingsEnd() override; - void OnSettingsAck(const Http2FrameHeader& header) override; - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override; - void OnPushPromiseEnd() override; - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override; - void OnGoAwayOpaqueData(const char* data, size_t len) override; - void OnGoAwayEnd() override; - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) override; - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override; - void OnAltSvcOriginData(const char* data, size_t len) override; - void OnAltSvcValueData(const char* data, size_t len) override; - void OnAltSvcEnd() override; - void OnPriorityUpdateStart( - const Http2FrameHeader& header, - const Http2PriorityUpdateFields& priority_update) override; - void OnPriorityUpdatePayload(const char* data, size_t len) override; - void OnPriorityUpdateEnd() override; - void OnUnknownStart(const Http2FrameHeader& header) override; - void OnUnknownPayload(const char* data, size_t len) override; - void OnUnknownEnd() override; - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override; - void OnFrameSizeError(const Http2FrameHeader& header) override; - - private: - void EnsureNotAbstract() { LoggingHttp2FrameDecoderListener instance; } - - Http2FrameDecoderListener* wrapped_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc deleted file mode 100644 index b3fd7233329..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc +++ /dev/null @@ -1,940 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/http2_frame_decoder.h" - -// Tests of Http2FrameDecoder. - -#include <string> -#include <vector> - -#include "absl/strings/string_view.h" -#include "http2/http2_constants.h" -#include "http2/platform/api/http2_flags.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector_listener.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/random_decoder_test.h" - -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -class Http2FrameDecoderPeer { - public: - static size_t remaining_total_payload(Http2FrameDecoder* decoder) { - return decoder->frame_decoder_state_.remaining_total_payload(); - } -}; - -namespace { - -class Http2FrameDecoderTest : public RandomDecoderTest { - protected: - void SetUp() override { - // On any one run of this suite, we'll always choose the same value for - // use_default_constructor_ because the random seed is the same for each - // test case, but across runs the random seed changes. - use_default_constructor_ = Random().OneIn(2); - } - - DecodeStatus StartDecoding(DecodeBuffer* db) override { - HTTP2_DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining(); - collector_.Reset(); - PrepareDecoder(); - - DecodeStatus status = decoder_->DecodeFrame(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++fast_decode_count_; - if (status == DecodeStatus::kDecodeError) { - ConfirmDiscardsRemainingPayload(); - } - } - return status; - } - - DecodeStatus ResumeDecoding(DecodeBuffer* db) override { - HTTP2_DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining(); - DecodeStatus status = decoder_->DecodeFrame(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++slow_decode_count_; - if (status == DecodeStatus::kDecodeError) { - ConfirmDiscardsRemainingPayload(); - } - } - return status; - } - - // When an error is returned, the decoder is in state kDiscardPayload, and - // stays there until the remaining bytes of the frame's payload have been - // skipped over. There are no callbacks for this situation. - void ConfirmDiscardsRemainingPayload() { - ASSERT_TRUE(decoder_->IsDiscardingPayload()); - size_t remaining = - Http2FrameDecoderPeer::remaining_total_payload(decoder_.get()); - // The decoder will discard the remaining bytes, but not go beyond that, - // which these conditions verify. - size_t extra = 10; - std::string junk(remaining + extra, '0'); - DecodeBuffer tmp(junk); - EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_->DecodeFrame(&tmp)); - EXPECT_EQ(remaining, tmp.Offset()); - EXPECT_EQ(extra, tmp.Remaining()); - EXPECT_FALSE(decoder_->IsDiscardingPayload()); - } - - void PrepareDecoder() { - // Alternate which constructor is used. - if (use_default_constructor_) { - decoder_ = std::make_unique<Http2FrameDecoder>(); - decoder_->set_listener(&collector_); - } else { - decoder_ = std::make_unique<Http2FrameDecoder>(&collector_); - } - decoder_->set_maximum_payload_size(maximum_payload_size_); - - use_default_constructor_ = !use_default_constructor_; - } - - void ResetDecodeSpeedCounters() { - fast_decode_count_ = 0; - slow_decode_count_ = 0; - } - - AssertionResult VerifyCollected(const FrameParts& expected) { - VERIFY_FALSE(collector_.IsInProgress()); - VERIFY_EQ(1u, collector_.size()); - VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*collector_.frame(0))); - } - - AssertionResult DecodePayloadAndValidateSeveralWays(absl::string_view payload, - Validator validator) { - DecodeBuffer db(payload); - bool start_decoding_requires_non_empty = false; - return DecodeAndValidateSeveralWays(&db, start_decoding_requires_non_empty, - validator); - } - - // Decode one frame's payload and confirm that the listener recorded the - // expected FrameParts instance, and only one FrameParts instance. The - // payload will be decoded several times with different partitionings - // of the payload, and after each the validator will be called. - AssertionResult DecodePayloadAndValidateSeveralWays( - absl::string_view payload, - const FrameParts& expected) { - auto validator = [&expected, this](const DecodeBuffer& /*input*/, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - }; - ResetDecodeSpeedCounters(); - VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays( - payload, ValidateDoneAndEmpty(validator))); - VERIFY_GT(fast_decode_count_, 0u); - VERIFY_GT(slow_decode_count_, 0u); - - // Repeat with more input; it should stop without reading that input. - std::string next_frame = Random().RandString(10); - std::string input(payload.data(), payload.size()); - input += next_frame; - - ResetDecodeSpeedCounters(); - VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays( - payload, ValidateDoneAndOffset(payload.size(), validator))); - VERIFY_GT(fast_decode_count_, 0u); - VERIFY_GT(slow_decode_count_, 0u); - - return AssertionSuccess(); - } - - template <size_t N> - AssertionResult DecodePayloadAndValidateSeveralWays( - const char (&buf)[N], - const FrameParts& expected) { - return DecodePayloadAndValidateSeveralWays(absl::string_view(buf, N), - expected); - } - - template <size_t N> - AssertionResult DecodePayloadAndValidateSeveralWays( - const char (&buf)[N], - const Http2FrameHeader& header) { - return DecodePayloadAndValidateSeveralWays(absl::string_view(buf, N), - FrameParts(header)); - } - - template <size_t N> - AssertionResult DecodePayloadExpectingError(const char (&buf)[N], - const FrameParts& expected) { - auto validator = [&expected, this](const DecodeBuffer& /*input*/, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeError); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - }; - ResetDecodeSpeedCounters(); - EXPECT_TRUE( - DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator)); - EXPECT_GT(fast_decode_count_, 0u); - EXPECT_GT(slow_decode_count_, 0u); - return AssertionSuccess(); - } - - template <size_t N> - AssertionResult DecodePayloadExpectingFrameSizeError(const char (&buf)[N], - FrameParts expected) { - expected.SetHasFrameSizeError(true); - VERIFY_AND_RETURN_SUCCESS(DecodePayloadExpectingError(buf, expected)); - } - - template <size_t N> - AssertionResult DecodePayloadExpectingFrameSizeError( - const char (&buf)[N], - const Http2FrameHeader& header) { - return DecodePayloadExpectingFrameSizeError(buf, FrameParts(header)); - } - - // Count of payloads that are fully decoded by StartDecodingPayload or for - // which an error was detected by StartDecodingPayload. - size_t fast_decode_count_ = 0; - - // Count of payloads that required calling ResumeDecodingPayload in order to - // decode completely, or for which an error was detected by - // ResumeDecodingPayload. - size_t slow_decode_count_ = 0; - - uint32_t maximum_payload_size_ = Http2SettingsInfo::DefaultMaxFrameSize(); - FramePartsCollectorListener collector_; - std::unique_ptr<Http2FrameDecoder> decoder_; - bool use_default_constructor_; -}; - -//////////////////////////////////////////////////////////////////////////////// -// Tests that pass the minimum allowed size for the frame type, which is often -// empty. The tests are in order by frame type value (i.e. 0 for DATA frames). - -TEST_F(Http2FrameDecoderTest, DataEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x00', // DATA - '\x00', // Flags: none - '\x00', '\x00', '\x00', - '\x00', // Stream ID: 0 (invalid but unchecked here) - }; - Http2FrameHeader header(0, Http2FrameType::DATA, 0, 0); - FrameParts expected(header, ""); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x01', // HEADERS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream ID: 0 (REQUIRES ID) - }; - Http2FrameHeader header(0, Http2FrameType::HEADERS, 0, 1); - FrameParts expected(header, ""); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, Priority) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Length: 5 - '\x02', // Type: PRIORITY - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream: 2 - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - '\x10', // Weight: 17 - }; - Http2FrameHeader header(5, Http2FrameType::PRIORITY, 0, 2); - FrameParts expected(header); - expected.SetOptPriority(Http2PriorityFields(1, 17, true)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, RstStream) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Length: 4 - '\x03', // Type: RST_STREAM - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR - }; - Http2FrameHeader header(4, Http2FrameType::RST_STREAM, 0, 1); - FrameParts expected(header); - expected.SetOptRstStreamErrorCode(Http2ErrorCode::PROTOCOL_ERROR); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, SettingsEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Length: 0 - '\x04', // Type: SETTINGS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here) - }; - Http2FrameHeader header(0, Http2FrameType::SETTINGS, 0, 1); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, SettingsAck) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Length: 6 - '\x04', // Type: SETTINGS - '\x01', // Flags: ACK - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - }; - Http2FrameHeader header(0, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromiseMinimal) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Payload length: 4 - '\x05', // PUSH_PROMISE - '\x04', // Flags: END_HEADERS - '\x00', '\x00', '\x00', - '\x02', // Stream: 2 (invalid but unchecked here) - '\x00', '\x00', '\x00', - '\x01', // Promised: 1 (invalid but unchecked here) - }; - Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::END_HEADERS, 2); - FrameParts expected(header, ""); - expected.SetOptPushPromise(Http2PushPromiseFields{1}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, Ping) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Length: 8 - '\x06', // Type: PING - '\xfe', // Flags: no valid flags - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" - }; - Http2FrameHeader header(8, Http2FrameType::PING, 0, 0); - FrameParts expected(header); - expected.SetOptPing( - Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PingAck) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Length: 8 - '\x06', // Type: PING - '\xff', // Flags: ACK (plus all invalid flags) - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" - }; - Http2FrameHeader header(8, Http2FrameType::PING, Http2FrameFlag::ACK, 0); - FrameParts expected(header); - expected.SetOptPing( - Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, GoAwayMinimal) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Length: 8 (no opaque data) - '\x07', // Type: GOAWAY - '\xff', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here) - '\x80', '\x00', '\x00', '\xff', // Last: 255 (plus R bit) - '\x00', '\x00', '\x00', '\x09', // Error: COMPRESSION_ERROR - }; - Http2FrameHeader header(8, Http2FrameType::GOAWAY, 0, 1); - FrameParts expected(header); - expected.SetOptGoaway( - Http2GoAwayFields(255, Http2ErrorCode::COMPRESSION_ERROR)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, WindowUpdate) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Length: 4 - '\x08', // Type: WINDOW_UPDATE - '\x0f', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit) - }; - Http2FrameHeader header(4, Http2FrameType::WINDOW_UPDATE, 0, 1); - FrameParts expected(header); - expected.SetOptWindowUpdateIncrement(1024); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, ContinuationEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x09', // CONTINUATION - '\x00', // Flags: none - '\x00', '\x00', '\x00', - '\x00', // Stream ID: 0 (invalid but unchecked here) - }; - Http2FrameHeader header(0, Http2FrameType::CONTINUATION, 0, 0); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcMinimal) { - const char kFrameData[] = { - '\x00', '\x00', '\x02', // Payload length: 2 - '\x0a', // ALTSVC - '\xff', // Flags: none (plus 0xff) - '\x00', '\x00', '\x00', - '\x00', // Stream ID: 0 (invalid but unchecked here) - '\x00', '\x00', // Origin Length: 0 - }; - Http2FrameHeader header(2, Http2FrameType::ALTSVC, 0, 0); - FrameParts expected(header); - expected.SetOptAltsvcOriginLength(0); - expected.SetOptAltsvcValueLength(0); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, UnknownEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x20', // 32 (unknown) - '\xff', // Flags: all - '\x00', '\x00', '\x00', '\x00', // Stream ID: 0 - }; - Http2FrameHeader header(0, static_cast<Http2FrameType>(32), 0xff, 0); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Tests of longer payloads, for those frame types that allow longer payloads. - -TEST_F(Http2FrameDecoderTest, DataPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 7 - '\x00', // DATA - '\x80', // Flags: 0x80 - '\x00', '\x00', '\x02', '\x02', // Stream ID: 514 - 'a', 'b', 'c', // Data - }; - Http2FrameHeader header(3, Http2FrameType::DATA, 0, 514); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 3 - '\x01', // HEADERS - '\x05', // Flags: END_STREAM | END_HEADERS - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - }; - Http2FrameHeader header( - 3, Http2FrameType::HEADERS, - Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS, 2); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPriority) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Payload length: 5 - '\x01', // HEADERS - '\x20', // Flags: PRIORITY - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x00', '\x00', '\x00', '\x01', // Parent: 1 (Not Exclusive) - '\xff', // Weight: 256 - }; - Http2FrameHeader header(5, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY, - 2); - FrameParts expected(header); - expected.SetOptPriority(Http2PriorityFields(1, 256, false)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, Settings) { - const char kFrameData[] = { - '\x00', '\x00', '\x0c', // Length: 12 - '\x04', // Type: SETTINGS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE - '\x0a', '\x0b', '\x0c', '\x0d', // Value: 168496141 - '\x00', '\x02', // Param: ENABLE_PUSH - '\x00', '\x00', '\x00', '\x03', // Value: 3 (invalid but unchecked here) - }; - Http2FrameHeader header(12, Http2FrameType::SETTINGS, 0, 0); - FrameParts expected(header); - expected.AppendSetting(Http2SettingFields( - Http2SettingsParameter::INITIAL_WINDOW_SIZE, 168496141)); - expected.AppendSetting( - Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromisePayload) { - const char kFrameData[] = { - '\x00', '\x00', 7, // Payload length: 7 - '\x05', // PUSH_PROMISE - '\x04', // Flags: END_HEADERS - '\x00', '\x00', '\x00', '\xff', // Stream ID: 255 - '\x00', '\x00', '\x01', '\x00', // Promised: 256 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - }; - Http2FrameHeader header(7, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::END_HEADERS, 255); - FrameParts expected(header, "abc"); - expected.SetOptPushPromise(Http2PushPromiseFields{256}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, GoAwayOpaqueData) { - const char kFrameData[] = { - '\x00', '\x00', '\x0e', // Length: 14 - '\x07', // Type: GOAWAY - '\xff', // Flags: 0xff (no valid flags) - '\x80', '\x00', '\x00', '\x00', // Stream: 0 (plus R bit) - '\x00', '\x00', '\x01', '\x00', // Last: 256 - '\x00', '\x00', '\x00', '\x03', // Error: FLOW_CONTROL_ERROR - 'o', 'p', 'a', 'q', 'u', 'e', - }; - Http2FrameHeader header(14, Http2FrameType::GOAWAY, 0, 0); - FrameParts expected(header, "opaque"); - expected.SetOptGoaway( - Http2GoAwayFields(256, Http2ErrorCode::FLOW_CONTROL_ERROR)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, ContinuationPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 3 - '\x09', // CONTINUATION - '\xff', // Flags: END_HEADERS | 0xfb - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - 'a', 'b', 'c', // Data - }; - Http2FrameHeader header(3, Http2FrameType::CONTINUATION, - Http2FrameFlag::END_HEADERS, 2); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Payload length: 3 - '\x0a', // ALTSVC - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - '\x00', '\x03', // Origin Length: 0 - 'a', 'b', 'c', // Origin - 'd', 'e', 'f', // Value - }; - Http2FrameHeader header(8, Http2FrameType::ALTSVC, 0, 2); - FrameParts expected(header); - expected.SetAltSvcExpected("abc", "def"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PriorityUpdatePayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Payload length: 7 - '\x10', // PRIORITY_UPDATE - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x00', // Stream ID: 0 - '\x00', '\x00', '\x00', '\x05', // Prioritized Stream ID: 5 - 'a', 'b', 'c', // Priority Field Value - }; - Http2FrameHeader header(7, Http2FrameType::PRIORITY_UPDATE, 0, 0); - - FrameParts expected(header, "abc"); - expected.SetOptPriorityUpdate(Http2PriorityUpdateFields{5}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, UnknownPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 3 - '\x30', // 48 (unknown) - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - 'a', 'b', 'c', // Payload - }; - Http2FrameHeader header(3, static_cast<Http2FrameType>(48), 0, 2); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Tests of padded payloads, for those frame types that allow padding. - -TEST_F(Http2FrameDecoderTest, DataPayloadAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Payload length: 7 - '\x00', // DATA - '\x09', // Flags: END_STREAM | PADDED - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - 'a', 'b', 'c', // Data - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(7, Http2FrameType::DATA, - Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED, - 2); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPayloadAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Payload length: 7 - '\x01', // HEADERS - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(7, Http2FrameType::HEADERS, Http2FrameFlag::PADDED, - 2); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPayloadPriorityAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', '\x0c', // Payload length: 12 - '\x01', // HEADERS - '\xff', // Flags: all, including undefined - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - '\x10', // Weight: 17 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(12, Http2FrameType::HEADERS, - Http2FrameFlag::END_STREAM | - Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY, - 2); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - expected.SetOptPriority(Http2PriorityFields(1, 17, true)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromisePayloadAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', 11, // Payload length: 11 - '\x05', // PUSH_PROMISE - '\xff', // Flags: END_HEADERS | PADDED | 0xf3 - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x03', // Pad Len - '\x00', '\x00', '\x00', '\x02', // Promised: 2 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(11, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED, - 1); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - expected.SetOptPushPromise(Http2PushPromiseFields{2}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Payload too short errors. - -TEST_F(Http2FrameDecoderTest, DataMissingPadLengthField) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x00', // DATA - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - }; - Http2FrameHeader header(0, Http2FrameType::DATA, Http2FrameFlag::PADDED, 1); - FrameParts expected(header); - expected.SetOptMissingLength(1); - EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeaderPaddingTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x02', // Payload length: 0 - '\x01', // HEADERS - '\x08', // Flags: PADDED - '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536 - '\xff', // Pad Len: 255 - '\x00', // Only one byte of padding - }; - Http2FrameHeader header(2, Http2FrameType::HEADERS, Http2FrameFlag::PADDED, - 65536); - FrameParts expected(header); - expected.SetOptMissingLength(254); - EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeaderMissingPriority) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Payload length: 0 - '\x01', // HEADERS - '\x20', // Flags: PRIORITY - '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536 - '\x00', '\x00', '\x00', '\x00', // Priority (truncated) - }; - Http2FrameHeader header(4, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY, - 65536); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PriorityTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Length: 5 - '\x02', // Type: PRIORITY - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream: 2 - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - }; - Http2FrameHeader header(4, Http2FrameType::PRIORITY, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, RstStreamTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Length: 4 - '\x03', // Type: RST_STREAM - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x00', '\x00', '\x00', // Truncated - }; - Http2FrameHeader header(3, Http2FrameType::RST_STREAM, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -// SETTINGS frames must a multiple of 6 bytes long, so an 9 byte payload is -// invalid. -TEST_F(Http2FrameDecoderTest, SettingsWrongSize) { - const char kFrameData[] = { - '\x00', '\x00', '\x09', // Length: 2 - '\x04', // Type: SETTINGS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - '\x00', '\x02', // Param: ENABLE_PUSH - '\x00', '\x00', '\x00', '\x03', // Value: 1 - '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE - '\x00', // Value: Truncated - }; - Http2FrameHeader header(9, Http2FrameType::SETTINGS, 0, 0); - FrameParts expected(header); - expected.AppendSetting( - Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3)); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromiseTooShort) { - const char kFrameData[] = { - '\x00', '\x00', 3, // Payload length: 3 - '\x05', // PUSH_PROMISE - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x00', '\x00', '\x00', // Truncated promise id - }; - Http2FrameHeader header(3, Http2FrameType::PUSH_PROMISE, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PushPromisePaddedTruncatedPromise) { - const char kFrameData[] = { - '\x00', '\x00', 4, // Payload length: 4 - '\x05', // PUSH_PROMISE - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x00', // Pad Len - '\x00', '\x00', '\x00', // Truncated promise id - }; - Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::PADDED, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PingTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Length: 8 - '\x06', // Type: PING - '\xfe', // Flags: no valid flags - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', // Too little - }; - Http2FrameHeader header(7, Http2FrameType::PING, 0, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, GoAwayTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Length: 0 - '\x07', // Type: GOAWAY - '\xff', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - }; - Http2FrameHeader header(0, Http2FrameType::GOAWAY, 0, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, WindowUpdateTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Length: 3 - '\x08', // Type: WINDOW_UPDATE - '\x0f', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x80', '\x00', '\x04', // Truncated - }; - Http2FrameHeader header(3, Http2FrameType::WINDOW_UPDATE, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOriginLength) { - const char kFrameData[] = { - '\x00', '\x00', '\x01', // Payload length: 3 - '\x0a', // ALTSVC - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - '\x00', // Origin Length: truncated - }; - Http2FrameHeader header(1, Http2FrameType::ALTSVC, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOrigin) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Payload length: 3 - '\x0a', // ALTSVC - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - '\x00', '\x04', // Origin Length: 4 (too long) - 'a', 'b', 'c', // Origin - }; - Http2FrameHeader header(5, Http2FrameType::ALTSVC, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Payload too long errors. - -// The decoder calls the listener's OnFrameSizeError method if the frame's -// payload is longer than the currently configured maximum payload size. -TEST_F(Http2FrameDecoderTest, BeyondMaximum) { - maximum_payload_size_ = 2; - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Payload length: 7 - '\x00', // DATA - '\x09', // Flags: END_STREAM | PADDED - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - 'a', 'b', 'c', // Data - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(7, Http2FrameType::DATA, - Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED, - 2); - FrameParts expected(header); - expected.SetHasFrameSizeError(true); - auto validator = [&expected, this](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeError); - // The decoder detects this error after decoding the header, and without - // trying to decode the payload. - VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize()); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - }; - ResetDecodeSpeedCounters(); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData), - validator)); - EXPECT_GT(fast_decode_count_, 0u); - EXPECT_GT(slow_decode_count_, 0u); -} - -TEST_F(Http2FrameDecoderTest, PriorityTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x06', // Length: 5 - '\x02', // Type: PRIORITY - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream: 2 - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - '\x10', // Weight: 17 - '\x00', // Too much - }; - Http2FrameHeader header(6, Http2FrameType::PRIORITY, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, RstStreamTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Length: 4 - '\x03', // Type: RST_STREAM - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR - '\x00', // Too much - }; - Http2FrameHeader header(5, Http2FrameType::RST_STREAM, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, SettingsAckTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x06', // Length: 6 - '\x04', // Type: SETTINGS - '\x01', // Flags: ACK - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - '\x00', '\x00', // Extra - '\x00', '\x00', '\x00', '\x00', // Extra - }; - Http2FrameHeader header(6, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PingAckTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x09', // Length: 8 - '\x06', // Type: PING - '\xff', // Flags: ACK | 0xfe - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" - '\x00', // Too much - }; - Http2FrameHeader header(9, Http2FrameType::PING, Http2FrameFlag::ACK, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, WindowUpdateTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Length: 5 - '\x08', // Type: WINDOW_UPDATE - '\x0f', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit) - '\x00', // Too much - }; - Http2FrameHeader header(5, Http2FrameType::WINDOW_UPDATE, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc deleted file mode 100644 index 43ade26797f..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/http2_structure_decoder.h" - -#include <algorithm> -#include <cstring> - -#include "http2/platform/api/http2_bug_tracker.h" - -namespace http2 { - -// Below we have some defensive coding: if we somehow run off the end, don't -// overwrite lots of memory. Note that most of this decoder is not defensive -// against bugs in the decoder, only against malicious encoders, but since -// we're copying memory into a buffer here, let's make sure we don't allow a -// small mistake to grow larger. The decoder will get stuck if we hit the -// HTTP2_BUG conditions, but shouldn't corrupt memory. - -uint32_t Http2StructureDecoder::IncompleteStart(DecodeBuffer* db, - uint32_t target_size) { - if (target_size > sizeof buffer_) { - HTTP2_BUG(http2_bug_154_1) - << "target_size too large for buffer: " << target_size; - return 0; - } - const uint32_t num_to_copy = db->MinLengthRemaining(target_size); - memcpy(buffer_, db->cursor(), num_to_copy); - offset_ = num_to_copy; - db->AdvanceCursor(num_to_copy); - return num_to_copy; -} - -DecodeStatus Http2StructureDecoder::IncompleteStart(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size) { - HTTP2_DVLOG(1) << "IncompleteStart@" << this - << ": *remaining_payload=" << *remaining_payload - << "; target_size=" << target_size - << "; db->Remaining=" << db->Remaining(); - *remaining_payload -= - IncompleteStart(db, std::min(target_size, *remaining_payload)); - if (*remaining_payload > 0 && db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - HTTP2_DVLOG(1) << "IncompleteStart: kDecodeError"; - return DecodeStatus::kDecodeError; -} - -bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db, - uint32_t target_size) { - HTTP2_DVLOG(2) << "ResumeFillingBuffer@" << this - << ": target_size=" << target_size << "; offset_=" << offset_ - << "; db->Remaining=" << db->Remaining(); - if (target_size < offset_) { - HTTP2_BUG(http2_bug_154_2) - << "Already filled buffer_! target_size=" << target_size - << " offset_=" << offset_; - return false; - } - const uint32_t needed = target_size - offset_; - const uint32_t num_to_copy = db->MinLengthRemaining(needed); - HTTP2_DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy; - memcpy(&buffer_[offset_], db->cursor(), num_to_copy); - db->AdvanceCursor(num_to_copy); - offset_ += num_to_copy; - return needed == num_to_copy; -} - -bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size) { - HTTP2_DVLOG(2) << "ResumeFillingBuffer@" << this - << ": target_size=" << target_size << "; offset_=" << offset_ - << "; *remaining_payload=" << *remaining_payload - << "; db->Remaining=" << db->Remaining(); - if (target_size < offset_) { - HTTP2_BUG(http2_bug_154_3) - << "Already filled buffer_! target_size=" << target_size - << " offset_=" << offset_; - return false; - } - const uint32_t needed = target_size - offset_; - const uint32_t num_to_copy = - db->MinLengthRemaining(std::min(needed, *remaining_payload)); - HTTP2_DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy; - memcpy(&buffer_[offset_], db->cursor(), num_to_copy); - db->AdvanceCursor(num_to_copy); - offset_ += num_to_copy; - *remaining_payload -= num_to_copy; - return needed == num_to_copy; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.h deleted file mode 100644 index 367e225afe8..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_ -#define QUICHE_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_ - -// Http2StructureDecoder is a class for decoding the fixed size structures in -// the HTTP/2 spec, defined in http2/http2_structures.h. This class -// is in aid of deciding whether to keep the SlowDecode methods which I -// (jamessynge) now think may not be worth their complexity. In particular, -// if most transport buffers are large, so it is rare that a structure is -// split across buffer boundaries, than the cost of buffering upon -// those rare occurrences is small, which then simplifies the callers. - -#include <cstdint> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_http2_structures.h" -#include "http2/decoder/decode_status.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class Http2StructureDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE Http2StructureDecoder { - public: - // The caller needs to keep track of whether to call Start or Resume. - // - // Start has an optimization for the case where the DecodeBuffer holds the - // entire encoded structure; in that case it decodes into *out and returns - // true, and does NOT touch the data members of the Http2StructureDecoder - // instance because the caller won't be calling Resume later. - // - // However, if the DecodeBuffer is too small to hold the entire encoded - // structure, Start copies the available bytes into the Http2StructureDecoder - // instance, and returns false to indicate that it has not been able to - // complete the decoding. - // - template <class S> - bool Start(S* out, DecodeBuffer* db) { - static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small"); - HTTP2_DVLOG(2) << __func__ << "@" << this - << ": db->Remaining=" << db->Remaining() - << "; EncodedSize=" << S::EncodedSize(); - if (db->Remaining() >= S::EncodedSize()) { - DoDecode(out, db); - return true; - } - IncompleteStart(db, S::EncodedSize()); - return false; - } - - template <class S> - bool Resume(S* out, DecodeBuffer* db) { - HTTP2_DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_ - << "; db->Remaining=" << db->Remaining(); - if (ResumeFillingBuffer(db, S::EncodedSize())) { - // We have the whole thing now. - HTTP2_DVLOG(2) << __func__ << "@" << this << " offset_=" << offset_ - << " Ready to decode from buffer_."; - DecodeBuffer buffer_db(buffer_, S::EncodedSize()); - DoDecode(out, &buffer_db); - return true; - } - QUICHE_DCHECK_LT(offset_, S::EncodedSize()); - return false; - } - - // A second pair of Start and Resume, where the caller has a variable, - // |remaining_payload| that is both tested for sufficiency and updated - // during decoding. Note that the decode buffer may extend beyond the - // remaining payload because the buffer may include padding. - template <class S> - DecodeStatus Start(S* out, DecodeBuffer* db, uint32_t* remaining_payload) { - static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small"); - HTTP2_DVLOG(2) << __func__ << "@" << this - << ": *remaining_payload=" << *remaining_payload - << "; db->Remaining=" << db->Remaining() - << "; EncodedSize=" << S::EncodedSize(); - if (db->MinLengthRemaining(*remaining_payload) >= S::EncodedSize()) { - DoDecode(out, db); - *remaining_payload -= S::EncodedSize(); - return DecodeStatus::kDecodeDone; - } - return IncompleteStart(db, remaining_payload, S::EncodedSize()); - } - - template <class S> - bool Resume(S* out, DecodeBuffer* db, uint32_t* remaining_payload) { - HTTP2_DVLOG(3) << __func__ << "@" << this << ": offset_=" << offset_ - << "; *remaining_payload=" << *remaining_payload - << "; db->Remaining=" << db->Remaining() - << "; EncodedSize=" << S::EncodedSize(); - if (ResumeFillingBuffer(db, remaining_payload, S::EncodedSize())) { - // We have the whole thing now. - HTTP2_DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_ - << "; Ready to decode from buffer_."; - DecodeBuffer buffer_db(buffer_, S::EncodedSize()); - DoDecode(out, &buffer_db); - return true; - } - QUICHE_DCHECK_LT(offset_, S::EncodedSize()); - return false; - } - - uint32_t offset() const { return offset_; } - - private: - friend class test::Http2StructureDecoderPeer; - - uint32_t IncompleteStart(DecodeBuffer* db, uint32_t target_size); - DecodeStatus IncompleteStart(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size); - - bool ResumeFillingBuffer(DecodeBuffer* db, uint32_t target_size); - bool ResumeFillingBuffer(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size); - - uint32_t offset_; - char buffer_[Http2FrameHeader::EncodedSize()]; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test.cc deleted file mode 100644 index afec9d4a909..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test.cc +++ /dev/null @@ -1,537 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/http2_structure_decoder.h" - -// Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined in -// http2/http2_structures.h) using Http2StructureDecoder, which -// handles buffering of structures split across input buffer boundaries, and in -// turn uses DoDecode when it has all of a structure in a contiguous buffer. - -// NOTE: This tests the first pair of Start and Resume, which don't take -// a remaining_payload parameter. The other pair are well tested via the -// payload decoder tests, though... -// TODO(jamessynge): Create type parameterized tests for Http2StructureDecoder -// where the type is the type of structure, and with testing of both pairs of -// Start and Resume methods; note that it appears that the first pair will be -// used only for Http2FrameHeader, and the other pair only for structures in the -// frame payload. - -#include <stddef.h> - -#include <cstdint> -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" - -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { -const bool kMayReturnZeroOnFirst = false; - -template <class S> -class Http2StructureDecoderTest : public RandomDecoderTest { - protected: - typedef S Structure; - - Http2StructureDecoderTest() { - // IF the test adds more data after the encoded structure, stop as - // soon as the structure is decoded. - stop_decode_on_done_ = true; - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - // Overwrite the current contents of |structure_|, into which we'll - // decode the buffer, so that we can be confident that we really decoded - // the structure every time. - structure_ = std::make_unique<S>(); - uint32_t old_remaining = b->Remaining(); - if (structure_decoder_.Start(structure_.get(), b)) { - EXPECT_EQ(old_remaining - S::EncodedSize(), b->Remaining()); - ++fast_decode_count_; - return DecodeStatus::kDecodeDone; - } else { - EXPECT_LT(structure_decoder_.offset(), S::EncodedSize()); - EXPECT_EQ(0u, b->Remaining()); - EXPECT_EQ(old_remaining - structure_decoder_.offset(), b->Remaining()); - ++incomplete_start_count_; - return DecodeStatus::kDecodeInProgress; - } - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - uint32_t old_offset = structure_decoder_.offset(); - EXPECT_LT(old_offset, S::EncodedSize()); - uint32_t avail = b->Remaining(); - if (structure_decoder_.Resume(structure_.get(), b)) { - EXPECT_LE(S::EncodedSize(), old_offset + avail); - EXPECT_EQ(b->Remaining(), avail - (S::EncodedSize() - old_offset)); - ++slow_decode_count_; - return DecodeStatus::kDecodeDone; - } else { - EXPECT_LT(structure_decoder_.offset(), S::EncodedSize()); - EXPECT_EQ(0u, b->Remaining()); - EXPECT_GT(S::EncodedSize(), old_offset + avail); - ++incomplete_resume_count_; - return DecodeStatus::kDecodeInProgress; - } - } - - // Fully decodes the Structure at the start of data, and confirms it matches - // *expected (if provided). - AssertionResult DecodeLeadingStructure(const S* expected, - absl::string_view data) { - VERIFY_LE(S::EncodedSize(), data.size()); - DecodeBuffer original(data); - - // The validator is called after each of the several times that the input - // DecodeBuffer is decoded, each with a different segmentation of the input. - // Validate that structure_ matches the expected value, if provided. - Validator validator; - if (expected != nullptr) { - validator = [expected, this](const DecodeBuffer& /*db*/, - DecodeStatus /*status*/) -> AssertionResult { - VERIFY_EQ(*expected, *structure_); - return AssertionSuccess(); - }; - } - - // Before that, validate that decoding is done and that we've advanced - // the cursor the expected amount. - validator = ValidateDoneAndOffset(S::EncodedSize(), validator); - - // Decode several times, with several segmentations of the input buffer. - fast_decode_count_ = 0; - slow_decode_count_ = 0; - incomplete_start_count_ = 0; - incomplete_resume_count_ = 0; - VERIFY_SUCCESS(DecodeAndValidateSeveralWays( - &original, kMayReturnZeroOnFirst, validator)); - VERIFY_FALSE(HasFailure()); - VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset()); - VERIFY_EQ(S::EncodedSize(), original.Offset()); - VERIFY_LT(0u, fast_decode_count_); - VERIFY_LT(0u, slow_decode_count_); - VERIFY_LT(0u, incomplete_start_count_); - - // If the structure is large enough so that SelectZeroOrOne will have - // caused Resume to return false, check that occurred. - if (S::EncodedSize() >= 2) { - VERIFY_LE(0u, incomplete_resume_count_); - } else { - VERIFY_EQ(0u, incomplete_resume_count_); - } - if (expected != nullptr) { - HTTP2_DVLOG(1) << "DecodeLeadingStructure expected: " << *expected; - HTTP2_DVLOG(1) << "DecodeLeadingStructure actual: " << *structure_; - VERIFY_EQ(*expected, *structure_); - } - return AssertionSuccess(); - } - - template <size_t N> - AssertionResult DecodeLeadingStructure(const char (&data)[N]) { - VERIFY_AND_RETURN_SUCCESS( - DecodeLeadingStructure(nullptr, absl::string_view(data, N))); - } - - template <size_t N> - AssertionResult DecodeLeadingStructure(const unsigned char (&data)[N]) { - VERIFY_AND_RETURN_SUCCESS( - DecodeLeadingStructure(nullptr, ToStringPiece(data))); - } - - // Encode the structure |in_s| into bytes, then decode the bytes - // and validate that the decoder produced the same field values. - AssertionResult EncodeThenDecode(const S& in_s) { - std::string bytes = SerializeStructure(in_s); - VERIFY_EQ(S::EncodedSize(), bytes.size()); - VERIFY_AND_RETURN_SUCCESS(DecodeLeadingStructure(&in_s, bytes)); - } - - // Repeatedly fill a structure with random but valid contents, encode it, then - // decode it, and finally validate that the decoded structure matches the - // random input. Lather-rinse-and-repeat. - AssertionResult TestDecodingRandomizedStructures(size_t count) { - for (size_t i = 0; i < count; ++i) { - Structure input; - Randomize(&input, RandomPtr()); - VERIFY_SUCCESS(EncodeThenDecode(input)); - } - return AssertionSuccess(); - } - - AssertionResult TestDecodingRandomizedStructures() { - VERIFY_SUCCESS(TestDecodingRandomizedStructures(100)); - return AssertionSuccess(); - } - - uint32_t decode_offset_ = 0; - std::unique_ptr<S> structure_; - Http2StructureDecoder structure_decoder_; - size_t fast_decode_count_ = 0; - size_t slow_decode_count_ = 0; - size_t incomplete_start_count_ = 0; - size_t incomplete_resume_count_ = 0; -}; - -class Http2FrameHeaderDecoderTest - : public Http2StructureDecoderTest<Http2FrameHeader> {}; - -TEST_F(Http2FrameHeaderDecoderTest, DecodesLiteral) { - { - // Realistic input. - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x05, // Payload length: 5 - 0x01, // Frame type: HEADERS - 0x08, // Flags: PADDED - 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 - 0x04, // Padding length: 4 - 0x00, 0x00, 0x00, 0x00, // Padding bytes - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(5u, structure_->payload_length); - EXPECT_EQ(Http2FrameType::HEADERS, structure_->type); - EXPECT_EQ(Http2FrameFlag::PADDED, structure_->flags); - EXPECT_EQ(1u, structure_->stream_id); - } - { - // Unlikely input. - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, 0xff, // Payload length: uint24 max - 0xff, // Frame type: Unknown - 0xff, // Flags: Unknown/All - 0xff, 0xff, 0xff, 0xff, // Stream ID: uint31 max, plus R-bit - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ((1u << 24) - 1u, structure_->payload_length); - EXPECT_EQ(static_cast<Http2FrameType>(255), structure_->type); - EXPECT_EQ(255, structure_->flags); - EXPECT_EQ(0x7FFFFFFFu, structure_->stream_id); - } -} - -TEST_F(Http2FrameHeaderDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2PriorityFieldsDecoderTest - : public Http2StructureDecoderTest<Http2PriorityFields> {}; - -TEST_F(Http2PriorityFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const unsigned char kData[] = { - 0x80, 0x00, 0x00, 0x05, // Exclusive (yes) and Dependency (5) - 0xff, // Weight: 256 (after adding 1) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(5u, structure_->stream_dependency); - EXPECT_EQ(256u, structure_->weight); - EXPECT_EQ(true, structure_->is_exclusive); - } - { - // clang-format off - const unsigned char kData[] = { - 0x7f, 0xff, 0xff, 0xff, // Excl. (no) and Dependency (uint31 max) - 0x00, // Weight: 1 (after adding 1) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_->stream_dependency); - EXPECT_EQ(1u, structure_->weight); - EXPECT_FALSE(structure_->is_exclusive); - } -} - -TEST_F(Http2PriorityFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2RstStreamFieldsDecoderTest - : public Http2StructureDecoderTest<Http2RstStreamFields> {}; - -TEST_F(Http2RstStreamFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_TRUE(structure_->IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_->error_code); - } - { - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, 0xff, 0xff, // Error: max uint32 (Unknown error code) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_FALSE(structure_->IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_->error_code); - } -} - -TEST_F(Http2RstStreamFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2SettingFieldsDecoderTest - : public Http2StructureDecoderTest<Http2SettingFields> {}; - -TEST_F(Http2SettingFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x01, // Setting: HEADER_TABLE_SIZE - 0x00, 0x00, 0x40, 0x00, // Value: 16K - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_TRUE(structure_->IsSupportedParameter()); - EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE, structure_->parameter); - EXPECT_EQ(1u << 14, structure_->value); - } - { - // clang-format off - const unsigned char kData[] = { - 0x00, 0x00, // Setting: Unknown (0) - 0xff, 0xff, 0xff, 0xff, // Value: max uint32 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_FALSE(structure_->IsSupportedParameter()); - EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_->parameter); - } -} - -TEST_F(Http2SettingFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2PushPromiseFieldsDecoderTest - : public Http2StructureDecoderTest<Http2PushPromiseFields> {}; - -TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const unsigned char kData[] = { - 0x00, 0x01, 0x8a, 0x92, // Promised Stream ID: 101010 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(101010u, structure_->promised_stream_id); - } - { - // Promised stream id has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - // clang-format off - const unsigned char kData[] = { - // Promised Stream ID: max uint31 and R-bit - 0xff, 0xff, 0xff, 0xff, - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_->promised_stream_id); - } -} - -TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2PingFieldsDecoderTest - : public Http2StructureDecoderTest<Http2PingFields> {}; - -TEST_F(Http2PingFieldsDecoderTest, DecodesLiteral) { - { - // Each byte is different, so can detect if order changed. - const char kData[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - }; - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_->opaque_bytes)); - } - { - // All zeros, detect problems handling NULs. - const char kData[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_->opaque_bytes)); - } - { - const unsigned char kData[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }; - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_->opaque_bytes)); - } -} - -TEST_F(Http2PingFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2GoAwayFieldsDecoderTest - : public Http2StructureDecoderTest<Http2GoAwayFields> {}; - -TEST_F(Http2GoAwayFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x00, // Last Stream ID: 0 - 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR (0) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(0u, structure_->last_stream_id); - EXPECT_TRUE(structure_->IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_->error_code); - } - { - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x01, // Last Stream ID: 1 - 0x00, 0x00, 0x00, 0x0d, // Error: HTTP_1_1_REQUIRED - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(1u, structure_->last_stream_id); - EXPECT_TRUE(structure_->IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_->error_code); - } - { - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, 0xff, 0xff, // Last Stream ID: max uint31 and R-bit - 0xff, 0xff, 0xff, 0xff, // Error: max uint32 (Unknown error code) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_->last_stream_id); // No high-bit. - EXPECT_FALSE(structure_->IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_->error_code); - } -} - -TEST_F(Http2GoAwayFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2WindowUpdateFieldsDecoderTest - : public Http2StructureDecoderTest<Http2WindowUpdateFields> {}; - -TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x01, 0x00, 0x00, // Window Size Increment: 2 ^ 16 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(1u << 16, structure_->window_size_increment); - } - { - // Increment must be non-zero, but we need to be able to decode the invalid - // zero to detect it. - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x00, // Window Size Increment: 0 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(0u, structure_->window_size_increment); - } - { - // Increment has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - // clang-format off - const unsigned char kData[] = { - // Window Size Increment: max uint31 and R-bit - 0xff, 0xff, 0xff, 0xff, - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_->window_size_increment); - } -} - -TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -//------------------------------------------------------------------------------ - -class Http2AltSvcFieldsDecoderTest - : public Http2StructureDecoderTest<Http2AltSvcFields> {}; - -TEST_F(Http2AltSvcFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x00, // Origin Length: 0 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(0, structure_->origin_length); - } - { - // clang-format off - const char kData[] = { - 0x00, 0x14, // Origin Length: 20 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(20, structure_->origin_length); - } - { - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, // Origin Length: uint16 max - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(65535, structure_->origin_length); - } -} - -TEST_F(Http2AltSvcFieldsDecoderTest, DecodesRandomized) { - EXPECT_TRUE(TestDecodingRandomizedStructures()); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.cc deleted file mode 100644 index 7fc66f6bc0f..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/http2_structure_decoder_test_util.h" - -#include <cstddef> - -namespace http2 { -namespace test { - -// static -void Http2StructureDecoderPeer::Randomize(Http2StructureDecoder* p, - Http2Random* rng) { - p->offset_ = rng->Rand32(); - for (size_t i = 0; i < sizeof p->buffer_; ++i) { - p->buffer_[i] = rng->Rand8(); - } -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.h b/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.h deleted file mode 100644 index 54031358d83..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_ -#define QUICHE_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_ - -#include "http2/decoder/http2_structure_decoder.h" - -#include "http2/test_tools/http2_random.h" - -namespace http2 { -namespace test { - -class Http2StructureDecoderPeer { - public: - // Overwrite the Http2StructureDecoder instance with random values. - static void Randomize(Http2StructureDecoder* p, Http2Random* rng); -}; - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc deleted file mode 100644 index f95417c6fe8..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/altsvc_payload_decoder.h" - -#include <stddef.h> - -#include "absl/base/macros.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - AltSvcPayloadDecoder::PayloadState v) { - switch (v) { - case AltSvcPayloadDecoder::PayloadState::kStartDecodingStruct: - return out << "kStartDecodingStruct"; - case AltSvcPayloadDecoder::PayloadState::kMaybeDecodedStruct: - return out << "kMaybeDecodedStruct"; - case AltSvcPayloadDecoder::PayloadState::kDecodingStrings: - return out << "kDecodingStrings"; - case AltSvcPayloadDecoder::PayloadState::kResumeDecodingStruct: - return out << "kResumeDecodingStruct"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG(http2_bug_163_1) - << "Invalid AltSvcPayloadDecoder::PayloadState: " << unknown; - return out << "AltSvcPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus AltSvcPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "AltSvcPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::ALTSVC, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - QUICHE_DCHECK_EQ(0, state->frame_header().flags); - - state->InitializeRemainders(); - payload_state_ = PayloadState::kStartDecodingStruct; - - return ResumeDecodingPayload(state, db); -} - -DecodeStatus AltSvcPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - HTTP2_DVLOG(2) << "AltSvcPayloadDecoder::ResumeDecodingPayload: " - << frame_header; - QUICHE_DCHECK_EQ(Http2FrameType::ALTSVC, frame_header.type); - QUICHE_DCHECK_LE(state->remaining_payload(), frame_header.payload_length); - QUICHE_DCHECK_LE(db->Remaining(), state->remaining_payload()); - QUICHE_DCHECK_NE(PayloadState::kMaybeDecodedStruct, payload_state_); - // |status| has to be initialized to some value to avoid compiler error in - // case PayloadState::kMaybeDecodedStruct below, but value does not matter, - // see QUICHE_DCHECK_NE above. - DecodeStatus status = DecodeStatus::kDecodeError; - while (true) { - HTTP2_DVLOG(2) - << "AltSvcPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kStartDecodingStruct: - status = state->StartDecodingStructureInPayload(&altsvc_fields_, db); - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kMaybeDecodedStruct: - if (status == DecodeStatus::kDecodeDone && - altsvc_fields_.origin_length <= state->remaining_payload()) { - size_t origin_length = altsvc_fields_.origin_length; - size_t value_length = state->remaining_payload() - origin_length; - state->listener()->OnAltSvcStart(frame_header, origin_length, - value_length); - } else if (status != DecodeStatus::kDecodeDone) { - QUICHE_DCHECK(state->remaining_payload() > 0 || - status == DecodeStatus::kDecodeError) - << "\nremaining_payload: " << state->remaining_payload() - << "\nstatus: " << status << "\nheader: " << frame_header; - // Assume in progress. - payload_state_ = PayloadState::kResumeDecodingStruct; - return status; - } else { - // The origin's length is longer than the remaining payload. - QUICHE_DCHECK_GT(altsvc_fields_.origin_length, - state->remaining_payload()); - return state->ReportFrameSizeError(); - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kDecodingStrings: - return DecodeStrings(state, db); - - case PayloadState::kResumeDecodingStruct: - status = state->ResumeDecodingStructureInPayload(&altsvc_fields_, db); - payload_state_ = PayloadState::kMaybeDecodedStruct; - continue; - } - HTTP2_BUG(http2_bug_163_2) << "PayloadState: " << payload_state_; - } -} - -DecodeStatus AltSvcPayloadDecoder::DecodeStrings(FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "AltSvcPayloadDecoder::DecodeStrings remaining_payload=" - << state->remaining_payload() - << ", db->Remaining=" << db->Remaining(); - // Note that we don't explicitly keep track of exactly how far through the - // origin; instead we compute it from how much is left of the original - // payload length and the decoded total length of the origin. - size_t origin_length = altsvc_fields_.origin_length; - size_t value_length = state->frame_header().payload_length - origin_length - - Http2AltSvcFields::EncodedSize(); - if (state->remaining_payload() > value_length) { - size_t remaining_origin_length = state->remaining_payload() - value_length; - size_t avail = db->MinLengthRemaining(remaining_origin_length); - state->listener()->OnAltSvcOriginData(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - if (remaining_origin_length > avail) { - payload_state_ = PayloadState::kDecodingStrings; - return DecodeStatus::kDecodeInProgress; - } - } - // All that is left is the value string. - QUICHE_DCHECK_LE(state->remaining_payload(), value_length); - QUICHE_DCHECK_LE(db->Remaining(), state->remaining_payload()); - if (db->HasData()) { - size_t avail = db->Remaining(); - state->listener()->OnAltSvcValueData(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() == 0) { - state->listener()->OnAltSvcEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kDecodingStrings; - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.h deleted file mode 100644 index 6a869c54230..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_ - -// Decodes the payload of a ALTSVC frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class AltSvcPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE AltSvcPayloadDecoder { - public: - // States during decoding of a ALTSVC frame. - enum class PayloadState { - // Start decoding the fixed size structure at the start of an ALTSVC - // frame (Http2AltSvcFields). - kStartDecodingStruct, - - // Handle the DecodeStatus returned from starting or resuming the - // decoding of Http2AltSvcFields. If complete, calls OnAltSvcStart. - kMaybeDecodedStruct, - - // Reports the value of the strings (origin and value) of an ALTSVC frame - // to the listener. - kDecodingStrings, - - // The initial decode buffer wasn't large enough for the Http2AltSvcFields, - // so this state resumes the decoding when ResumeDecodingPayload is called - // later with a new DecodeBuffer. - kResumeDecodingStruct, - }; - - // Starts the decoding of a ALTSVC frame's payload, and completes it if the - // entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a ALTSVC frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::AltSvcPayloadDecoderPeer; - - // Implements state kDecodingStrings. - DecodeStatus DecodeStrings(FrameDecoderState* state, DecodeBuffer* db); - - Http2AltSvcFields altsvc_fields_; - PayloadState payload_state_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc deleted file mode 100644 index cecd1f9809c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/altsvc_payload_decoder.h" - -#include <stddef.h> - -#include <string> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class AltSvcPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::ALTSVC; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override { - HTTP2_VLOG(1) << "OnAltSvcStart header: " << header - << "; origin_length=" << origin_length - << "; value_length=" << value_length; - StartFrame(header)->OnAltSvcStart(header, origin_length, value_length); - } - - void OnAltSvcOriginData(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnAltSvcOriginData: len=" << len; - CurrentFrame()->OnAltSvcOriginData(data, len); - } - - void OnAltSvcValueData(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnAltSvcValueData: len=" << len; - CurrentFrame()->OnAltSvcValueData(data, len); - } - - void OnAltSvcEnd() override { - HTTP2_VLOG(1) << "OnAltSvcEnd"; - EndFrame()->OnAltSvcEnd(); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class AltSvcPayloadDecoderTest - : public AbstractPayloadDecoderTest<AltSvcPayloadDecoder, - AltSvcPayloadDecoderPeer, - Listener> {}; - -// Confirm we get an error if the payload is not long enough to hold -// Http2AltSvcFields and the indicated length of origin. -TEST_F(AltSvcPayloadDecoderTest, Truncated) { - Http2FrameBuilder fb; - fb.Append(Http2AltSvcFields{0xffff}); // The longest possible origin length. - fb.Append("Too little origin!"); - EXPECT_TRUE( - VerifyDetectsFrameSizeError(0, fb.buffer(), /*approve_size*/ nullptr)); -} - -class AltSvcPayloadLengthTests : public AltSvcPayloadDecoderTest, - public ::testing::WithParamInterface< - ::testing::tuple<uint16_t, uint32_t>> { - protected: - AltSvcPayloadLengthTests() - : origin_length_(::testing::get<0>(GetParam())), - value_length_(::testing::get<1>(GetParam())) { - HTTP2_VLOG(1) << "################ origin_length_=" << origin_length_ - << " value_length_=" << value_length_ - << " ################"; - } - - const uint16_t origin_length_; - const uint32_t value_length_; -}; - -INSTANTIATE_TEST_SUITE_P(VariousOriginAndValueLengths, - AltSvcPayloadLengthTests, - ::testing::Combine(::testing::Values(0, 1, 3, 65535), - ::testing::Values(0, 1, 3, 65537))); - -TEST_P(AltSvcPayloadLengthTests, ValidOriginAndValueLength) { - std::string origin = Random().RandString(origin_length_); - std::string value = Random().RandString(value_length_); - Http2FrameBuilder fb; - fb.Append(Http2AltSvcFields{origin_length_}); - fb.Append(origin); - fb.Append(value); - Http2FrameHeader header(fb.size(), Http2FrameType::ALTSVC, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetAltSvcExpected(origin, value); - ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.cc deleted file mode 100644 index 10e9d95beb3..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/continuation_payload_decoder.h" - -#include <stddef.h> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -DecodeStatus ContinuationPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - HTTP2_DVLOG(2) << "ContinuationPayloadDecoder::StartDecodingPayload: " - << frame_header; - QUICHE_DCHECK_EQ(Http2FrameType::CONTINUATION, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), total_length); - QUICHE_DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::END_HEADERS)); - - state->InitializeRemainders(); - state->listener()->OnContinuationStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus ContinuationPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "ContinuationPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - QUICHE_DCHECK_EQ(Http2FrameType::CONTINUATION, state->frame_header().type); - QUICHE_DCHECK_LE(state->remaining_payload(), - state->frame_header().payload_length); - QUICHE_DCHECK_LE(db->Remaining(), state->remaining_payload()); - - size_t avail = db->Remaining(); - QUICHE_DCHECK_LE(avail, state->remaining_payload()); - if (avail > 0) { - state->listener()->OnHpackFragment(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() == 0) { - state->listener()->OnContinuationEnd(); - return DecodeStatus::kDecodeDone; - } - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.h deleted file mode 100644 index d4ea98ba52a..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_ - -// Decodes the payload of a CONTINUATION frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE ContinuationPayloadDecoder { - public: - // Starts the decoding of a CONTINUATION frame's payload, and completes - // it if the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a CONTINUATION frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc deleted file mode 100644 index ec88306fc60..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/continuation_payload_decoder.h" - -#include <stddef.h> - -#include <string> -#include <type_traits> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class ContinuationPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::CONTINUATION; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnContinuationStart(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnContinuationStart: " << header; - StartFrame(header)->OnContinuationStart(header); - } - - void OnHpackFragment(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnHpackFragment: len=" << len; - CurrentFrame()->OnHpackFragment(data, len); - } - - void OnContinuationEnd() override { - HTTP2_VLOG(1) << "OnContinuationEnd"; - EndFrame()->OnContinuationEnd(); - } -}; - -class ContinuationPayloadDecoderTest - : public AbstractPayloadDecoderTest<ContinuationPayloadDecoder, - ContinuationPayloadDecoderPeer, - Listener>, - public ::testing::WithParamInterface<uint32_t> { - protected: - ContinuationPayloadDecoderTest() : length_(GetParam()) { - HTTP2_VLOG(1) << "################ length_=" << length_ - << " ################"; - } - - const uint32_t length_; -}; - -INSTANTIATE_TEST_SUITE_P(VariousLengths, - ContinuationPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 5, 6)); - -TEST_P(ContinuationPayloadDecoderTest, ValidLength) { - std::string hpack_payload = Random().RandString(length_); - Http2FrameHeader frame_header(length_, Http2FrameType::CONTINUATION, - RandFlags(), RandStreamId()); - set_frame_header(frame_header); - FrameParts expected(frame_header, hpack_payload); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(hpack_payload, expected)); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc deleted file mode 100644 index 523ead1d5b1..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/data_payload_decoder.h" - -#include <stddef.h> - -#include "absl/base/macros.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - DataPayloadDecoder::PayloadState v) { - switch (v) { - case DataPayloadDecoder::PayloadState::kReadPadLength: - return out << "kReadPadLength"; - case DataPayloadDecoder::PayloadState::kReadPayload: - return out << "kReadPayload"; - case DataPayloadDecoder::PayloadState::kSkipPadding: - return out << "kSkipPadding"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG(http2_bug_174_1) - << "Invalid DataPayloadDecoder::PayloadState: " << unknown; - return out << "DataPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus DataPayloadDecoder::StartDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - HTTP2_DVLOG(2) << "DataPayloadDecoder::StartDecodingPayload: " - << frame_header; - QUICHE_DCHECK_EQ(Http2FrameType::DATA, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), total_length); - QUICHE_DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::END_STREAM | - Http2FrameFlag::PADDED)); - - // Special case for the hoped for common case: unpadded and fits fully into - // the decode buffer. TO BE SEEN if that is true. It certainly requires that - // the transport buffers be large (e.g. >> 16KB typically). - // TODO(jamessynge) Add counters. - HTTP2_DVLOG(2) << "StartDecodingPayload total_length=" << total_length; - if (!frame_header.IsPadded()) { - HTTP2_DVLOG(2) << "StartDecodingPayload !IsPadded"; - if (db->Remaining() == total_length) { - HTTP2_DVLOG(2) << "StartDecodingPayload all present"; - // Note that we don't cache the listener field so that the callee can - // replace it if the frame is bad. - // If this case is common enough, consider combining the 3 callbacks - // into one. - state->listener()->OnDataStart(frame_header); - if (total_length > 0) { - state->listener()->OnDataPayload(db->cursor(), total_length); - db->AdvanceCursor(total_length); - } - state->listener()->OnDataEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kReadPayload; - } else { - payload_state_ = PayloadState::kReadPadLength; - } - state->InitializeRemainders(); - state->listener()->OnDataStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus DataPayloadDecoder::ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "DataPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - const Http2FrameHeader& frame_header = state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::DATA, frame_header.type); - QUICHE_DCHECK_LE(state->remaining_payload_and_padding(), - frame_header.payload_length); - QUICHE_DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding()); - DecodeStatus status; - size_t avail; - switch (payload_state_) { - case PayloadState::kReadPadLength: - // ReadPadLength handles the OnPadLength callback, and updating the - // remaining_payload and remaining_padding fields. If the amount of - // padding is too large to fit in the frame's payload, ReadPadLength - // instead calls OnPaddingTooLong and returns kDecodeError. - status = state->ReadPadLength(db, /*report_pad_length*/ true); - if (status != DecodeStatus::kDecodeDone) { - return status; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kReadPayload: - avail = state->AvailablePayload(db); - if (avail > 0) { - state->listener()->OnDataPayload(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadPayload; - return DecodeStatus::kDecodeInProgress; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kSkipPadding: - // SkipPadding handles the OnPadding callback. - if (state->SkipPadding(db)) { - state->listener()->OnDataEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kSkipPadding; - return DecodeStatus::kDecodeInProgress; - } - HTTP2_BUG(http2_bug_174_2) << "PayloadState: " << payload_state_; - return DecodeStatus::kDecodeError; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.h deleted file mode 100644 index 89fe4179c3c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_ - -// Decodes the payload of a DATA frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class DataPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE DataPayloadDecoder { - public: - // States during decoding of a DATA frame. - enum class PayloadState { - // The frame is padded and we need to read the PAD_LENGTH field (1 byte), - // and then call OnPadLength - kReadPadLength, - - // Report the non-padding portion of the payload to the listener's - // OnDataPayload method. - kReadPayload, - - // The decoder has finished with the non-padding portion of the payload, - // and is now ready to skip the trailing padding, if the frame has any. - kSkipPadding, - }; - - // Starts decoding a DATA frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a DATA frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::DataPayloadDecoderPeer; - - PayloadState payload_state_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder_test.cc deleted file mode 100644 index aa7b5e848c7..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder_test.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/data_payload_decoder.h" - -#include <stddef.h> - -#include <string> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class DataPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::DATA; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::PADDED; - } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnDataStart(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnDataStart: " << header; - StartFrame(header)->OnDataStart(header); - } - - void OnDataPayload(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnDataPayload: len=" << len; - CurrentFrame()->OnDataPayload(data, len); - } - - void OnDataEnd() override { - HTTP2_VLOG(1) << "OnDataEnd"; - EndFrame()->OnDataEnd(); - } - - void OnPadLength(size_t pad_length) override { - HTTP2_VLOG(1) << "OnPadLength: " << pad_length; - CurrentFrame()->OnPadLength(pad_length); - } - - void OnPadding(const char* padding, size_t skipped_length) override { - HTTP2_VLOG(1) << "OnPadding: " << skipped_length; - CurrentFrame()->OnPadding(padding, skipped_length); - } - - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override { - HTTP2_VLOG(1) << "OnPaddingTooLong: " << header - << " missing_length: " << missing_length; - EndFrame()->OnPaddingTooLong(header, missing_length); - } -}; - -class DataPayloadDecoderTest - : public AbstractPaddablePayloadDecoderTest<DataPayloadDecoder, - DataPayloadDecoderPeer, - Listener> { - protected: - AssertionResult CreateAndDecodeDataOfSize(size_t data_size) { - Reset(); - uint8_t flags = RandFlags(); - - std::string data_payload = Random().RandString(data_size); - frame_builder_.Append(data_payload); - MaybeAppendTrailingPadding(); - - Http2FrameHeader frame_header(frame_builder_.size(), Http2FrameType::DATA, - flags, RandStreamId()); - set_frame_header(frame_header); - ScrubFlagsOfHeader(&frame_header); - FrameParts expected(frame_header, data_payload, total_pad_length_); - VERIFY_AND_RETURN_SUCCESS( - DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected)); - } -}; - -INSTANTIATE_TEST_SUITE_P(VariousPadLengths, - DataPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256)); - -TEST_P(DataPayloadDecoderTest, VariousDataPayloadSizes) { - for (size_t data_size : {0, 1, 2, 3, 255, 256, 1024}) { - EXPECT_TRUE(CreateAndDecodeDataOfSize(data_size)); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc deleted file mode 100644 index 3231feb5de8..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/goaway_payload_decoder.h" - -#include <stddef.h> - -#include "absl/base/macros.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - GoAwayPayloadDecoder::PayloadState v) { - switch (v) { - case GoAwayPayloadDecoder::PayloadState::kStartDecodingFixedFields: - return out << "kStartDecodingFixedFields"; - case GoAwayPayloadDecoder::PayloadState::kHandleFixedFieldsStatus: - return out << "kHandleFixedFieldsStatus"; - case GoAwayPayloadDecoder::PayloadState::kReadOpaqueData: - return out << "kReadOpaqueData"; - case GoAwayPayloadDecoder::PayloadState::kResumeDecodingFixedFields: - return out << "kResumeDecodingFixedFields"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG(http2_bug_167_1) - << "Invalid GoAwayPayloadDecoder::PayloadState: " << unknown; - return out << "GoAwayPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus GoAwayPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "GoAwayPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::GOAWAY, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - QUICHE_DCHECK_EQ(0, state->frame_header().flags); - - state->InitializeRemainders(); - payload_state_ = PayloadState::kStartDecodingFixedFields; - return ResumeDecodingPayload(state, db); -} - -DecodeStatus GoAwayPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) - << "GoAwayPayloadDecoder::ResumeDecodingPayload: remaining_payload=" - << state->remaining_payload() << ", db->Remaining=" << db->Remaining(); - - const Http2FrameHeader& frame_header = state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::GOAWAY, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), frame_header.payload_length); - QUICHE_DCHECK_NE(PayloadState::kHandleFixedFieldsStatus, payload_state_); - - // |status| has to be initialized to some value to avoid compiler error in - // case PayloadState::kHandleFixedFieldsStatus below, but value does not - // matter, see QUICHE_DCHECK_NE above. - DecodeStatus status = DecodeStatus::kDecodeError; - size_t avail; - while (true) { - HTTP2_DVLOG(2) - << "GoAwayPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kStartDecodingFixedFields: - status = state->StartDecodingStructureInPayload(&goaway_fields_, db); - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kHandleFixedFieldsStatus: - if (status == DecodeStatus::kDecodeDone) { - state->listener()->OnGoAwayStart(frame_header, goaway_fields_); - } else { - // Not done decoding the structure. Either we've got more payload - // to decode, or we've run out because the payload is too short, - // in which case OnFrameSizeError will have already been called. - QUICHE_DCHECK((status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && - state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - payload_state_ = PayloadState::kResumeDecodingFixedFields; - return status; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kReadOpaqueData: - // The opaque data is all the remains to be decoded, so anything left - // in the decode buffer is opaque data. - avail = db->Remaining(); - if (avail > 0) { - state->listener()->OnGoAwayOpaqueData(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadOpaqueData; - return DecodeStatus::kDecodeInProgress; - } - state->listener()->OnGoAwayEnd(); - return DecodeStatus::kDecodeDone; - - case PayloadState::kResumeDecodingFixedFields: - status = state->ResumeDecodingStructureInPayload(&goaway_fields_, db); - payload_state_ = PayloadState::kHandleFixedFieldsStatus; - continue; - } - HTTP2_BUG(http2_bug_167_2) << "PayloadState: " << payload_state_; - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.h deleted file mode 100644 index cbffa43d8b8..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_ - -// Decodes the payload of a GOAWAY frame. - -// TODO(jamessynge): Sweep through all payload decoders, changing the names of -// the PayloadState enums so that they are really states, and not actions. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class GoAwayPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE GoAwayPayloadDecoder { - public: - // States during decoding of a GOAWAY frame. - enum class PayloadState { - // At the start of the GOAWAY frame payload, ready to start decoding the - // fixed size fields into goaway_fields_. - kStartDecodingFixedFields, - - // Handle the DecodeStatus returned from starting or resuming the - // decoding of Http2GoAwayFields into goaway_fields_. If complete, - // calls OnGoAwayStart. - kHandleFixedFieldsStatus, - - // Report the Opaque Data portion of the payload to the listener's - // OnGoAwayOpaqueData method, and call OnGoAwayEnd when the end of the - // payload is reached. - kReadOpaqueData, - - // The fixed size fields weren't all available when the decoder first - // tried to decode them (state kStartDecodingFixedFields); this state - // resumes the decoding when ResumeDecodingPayload is called later. - kResumeDecodingFixedFields, - }; - - // Starts the decoding of a GOAWAY frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a GOAWAY frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::GoAwayPayloadDecoderPeer; - - Http2GoAwayFields goaway_fields_; - PayloadState payload_state_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc deleted file mode 100644 index df64f20cf8c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/goaway_payload_decoder.h" - -#include <stddef.h> - -#include <string> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class GoAwayPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::GOAWAY; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override { - HTTP2_VLOG(1) << "OnGoAwayStart header: " << header - << "; goaway: " << goaway; - StartFrame(header)->OnGoAwayStart(header, goaway); - } - - void OnGoAwayOpaqueData(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnGoAwayOpaqueData: len=" << len; - CurrentFrame()->OnGoAwayOpaqueData(data, len); - } - - void OnGoAwayEnd() override { - HTTP2_VLOG(1) << "OnGoAwayEnd"; - EndFrame()->OnGoAwayEnd(); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class GoAwayPayloadDecoderTest - : public AbstractPayloadDecoderTest<GoAwayPayloadDecoder, - GoAwayPayloadDecoderPeer, - Listener> {}; - -// Confirm we get an error if the payload is not long enough to hold -// Http2GoAwayFields. -TEST_F(GoAwayPayloadDecoderTest, Truncated) { - auto approve_size = [](size_t size) { - return size != Http2GoAwayFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(Http2GoAwayFields(123, Http2ErrorCode::ENHANCE_YOUR_CALM)); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -class GoAwayOpaqueDataLengthTests - : public GoAwayPayloadDecoderTest, - public ::testing::WithParamInterface<uint32_t> { - protected: - GoAwayOpaqueDataLengthTests() : length_(GetParam()) { - HTTP2_VLOG(1) << "################ length_=" << length_ - << " ################"; - } - - const uint32_t length_; -}; - -INSTANTIATE_TEST_SUITE_P(VariousLengths, - GoAwayOpaqueDataLengthTests, - ::testing::Values(0, 1, 2, 3, 4, 5, 6)); - -TEST_P(GoAwayOpaqueDataLengthTests, ValidLength) { - Http2GoAwayFields goaway; - Randomize(&goaway, RandomPtr()); - std::string opaque_data = Random().RandString(length_); - Http2FrameBuilder fb; - fb.Append(goaway); - fb.Append(opaque_data); - Http2FrameHeader header(fb.size(), Http2FrameType::GOAWAY, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header, opaque_data); - expected.SetOptGoaway(goaway); - ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc deleted file mode 100644 index 5ae1f996cfd..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/headers_payload_decoder.h" - -#include <stddef.h> - -#include "absl/base/macros.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - HeadersPayloadDecoder::PayloadState v) { - switch (v) { - case HeadersPayloadDecoder::PayloadState::kReadPadLength: - return out << "kReadPadLength"; - case HeadersPayloadDecoder::PayloadState::kStartDecodingPriorityFields: - return out << "kStartDecodingPriorityFields"; - case HeadersPayloadDecoder::PayloadState::kResumeDecodingPriorityFields: - return out << "kResumeDecodingPriorityFields"; - case HeadersPayloadDecoder::PayloadState::kReadPayload: - return out << "kReadPayload"; - case HeadersPayloadDecoder::PayloadState::kSkipPadding: - return out << "kSkipPadding"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG(http2_bug_189_1) - << "Invalid HeadersPayloadDecoder::PayloadState: " << unknown; - return out << "HeadersPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus HeadersPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - HTTP2_DVLOG(2) << "HeadersPayloadDecoder::StartDecodingPayload: " - << frame_header; - - QUICHE_DCHECK_EQ(Http2FrameType::HEADERS, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), total_length); - QUICHE_DCHECK_EQ( - 0, frame_header.flags & - ~(Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY)); - - // Special case for HEADERS frames that contain only the HPACK block - // (fragment or whole) and that fit fully into the decode buffer. - // Why? Unencoded browser GET requests are typically under 1K and HPACK - // commonly shrinks request headers by 80%, so we can expect this to - // be common. - // TODO(jamessynge) Add counters here and to Spdy for determining how - // common this situation is. A possible approach is to create a - // Http2FrameDecoderListener that counts the callbacks and then forwards - // them on to another listener, which makes it easy to add and remove - // counting on a connection or even frame basis. - - // PADDED and PRIORITY both extra steps to decode, but if neither flag is - // set then we can decode faster. - const auto payload_flags = Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY; - if (!frame_header.HasAnyFlags(payload_flags)) { - HTTP2_DVLOG(2) << "StartDecodingPayload !IsPadded && !HasPriority"; - if (db->Remaining() == total_length) { - HTTP2_DVLOG(2) << "StartDecodingPayload all present"; - // Note that we don't cache the listener field so that the callee can - // replace it if the frame is bad. - // If this case is common enough, consider combining the 3 callbacks - // into one, especially if END_HEADERS is also set. - state->listener()->OnHeadersStart(frame_header); - if (total_length > 0) { - state->listener()->OnHpackFragment(db->cursor(), total_length); - db->AdvanceCursor(total_length); - } - state->listener()->OnHeadersEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kReadPayload; - } else if (frame_header.IsPadded()) { - payload_state_ = PayloadState::kReadPadLength; - } else { - QUICHE_DCHECK(frame_header.HasPriority()) << frame_header; - payload_state_ = PayloadState::kStartDecodingPriorityFields; - } - state->InitializeRemainders(); - state->listener()->OnHeadersStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus HeadersPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "HeadersPayloadDecoder::ResumeDecodingPayload " - << "remaining_payload=" << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - - const Http2FrameHeader& frame_header = state->frame_header(); - - QUICHE_DCHECK_EQ(Http2FrameType::HEADERS, frame_header.type); - QUICHE_DCHECK_LE(state->remaining_payload_and_padding(), - frame_header.payload_length); - QUICHE_DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding()); - DecodeStatus status; - size_t avail; - while (true) { - HTTP2_DVLOG(2) - << "HeadersPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kReadPadLength: - // ReadPadLength handles the OnPadLength callback, and updating the - // remaining_payload and remaining_padding fields. If the amount of - // padding is too large to fit in the frame's payload, ReadPadLength - // instead calls OnPaddingTooLong and returns kDecodeError. - status = state->ReadPadLength(db, /*report_pad_length*/ true); - if (status != DecodeStatus::kDecodeDone) { - return status; - } - if (!frame_header.HasPriority()) { - payload_state_ = PayloadState::kReadPayload; - continue; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kStartDecodingPriorityFields: - status = state->StartDecodingStructureInPayload(&priority_fields_, db); - if (status != DecodeStatus::kDecodeDone) { - payload_state_ = PayloadState::kResumeDecodingPriorityFields; - return status; - } - state->listener()->OnHeadersPriority(priority_fields_); - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kReadPayload: - avail = state->AvailablePayload(db); - if (avail > 0) { - state->listener()->OnHpackFragment(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadPayload; - return DecodeStatus::kDecodeInProgress; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kSkipPadding: - // SkipPadding handles the OnPadding callback. - if (state->SkipPadding(db)) { - state->listener()->OnHeadersEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kSkipPadding; - return DecodeStatus::kDecodeInProgress; - - case PayloadState::kResumeDecodingPriorityFields: - status = state->ResumeDecodingStructureInPayload(&priority_fields_, db); - if (status != DecodeStatus::kDecodeDone) { - return status; - } - state->listener()->OnHeadersPriority(priority_fields_); - payload_state_ = PayloadState::kReadPayload; - continue; - } - HTTP2_BUG(http2_bug_189_2) << "PayloadState: " << payload_state_; - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.h deleted file mode 100644 index c56417d4f5a..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_ - -// Decodes the payload of a HEADERS frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class HeadersPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE HeadersPayloadDecoder { - public: - // States during decoding of a HEADERS frame, unless the fast path kicks - // in, in which case the state machine will be bypassed. - enum class PayloadState { - // The PADDED flag is set, and we now need to read the Pad Length field - // (the first byte of the payload, after the common frame header). - kReadPadLength, - - // The PRIORITY flag is set, and we now need to read the fixed size priority - // fields (E, Stream Dependency, Weight) into priority_fields_. Calls on - // OnHeadersPriority if completely decodes those fields. - kStartDecodingPriorityFields, - - // The decoder passes the non-padding portion of the remaining payload - // (i.e. the HPACK block fragment) to the listener's OnHpackFragment method. - kReadPayload, - - // The decoder has finished with the HPACK block fragment, and is now - // ready to skip the trailing padding, if the frame has any. - kSkipPadding, - - // The fixed size fields weren't all available when the decoder first tried - // to decode them (state kStartDecodingPriorityFields); this state resumes - // the decoding when ResumeDecodingPayload is called later. - kResumeDecodingPriorityFields, - }; - - // Starts the decoding of a HEADERS frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a HEADERS frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::HeadersPayloadDecoderPeer; - - PayloadState payload_state_; - Http2PriorityFields priority_fields_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder_test.cc deleted file mode 100644 index a2172335487..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder_test.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/headers_payload_decoder.h" - -#include <stddef.h> - -#include <string> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class HeadersPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::HEADERS; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY; - } -}; - -namespace { - -// Listener handles all On* methods that are expected to be called. If any other -// On* methods of Http2FrameDecoderListener is called then the test fails; this -// is achieved by way of FailingHttp2FrameDecoderListener, the base class of -// FramePartsCollector. -// These On* methods make use of StartFrame, EndFrame, etc. of the base class -// to create and access to FrameParts instance(s) that will record the details. -// After decoding, the test validation code can access the FramePart instance(s) -// via the public methods of FramePartsCollector. -struct Listener : public FramePartsCollector { - void OnHeadersStart(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnHeadersStart: " << header; - StartFrame(header)->OnHeadersStart(header); - } - - void OnHeadersPriority(const Http2PriorityFields& priority) override { - HTTP2_VLOG(1) << "OnHeadersPriority: " << priority; - CurrentFrame()->OnHeadersPriority(priority); - } - - void OnHpackFragment(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnHpackFragment: len=" << len; - CurrentFrame()->OnHpackFragment(data, len); - } - - void OnHeadersEnd() override { - HTTP2_VLOG(1) << "OnHeadersEnd"; - EndFrame()->OnHeadersEnd(); - } - - void OnPadLength(size_t pad_length) override { - HTTP2_VLOG(1) << "OnPadLength: " << pad_length; - CurrentFrame()->OnPadLength(pad_length); - } - - void OnPadding(const char* padding, size_t skipped_length) override { - HTTP2_VLOG(1) << "OnPadding: " << skipped_length; - CurrentFrame()->OnPadding(padding, skipped_length); - } - - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override { - HTTP2_VLOG(1) << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; - FrameError(header)->OnPaddingTooLong(header, missing_length); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class HeadersPayloadDecoderTest - : public AbstractPaddablePayloadDecoderTest<HeadersPayloadDecoder, - HeadersPayloadDecoderPeer, - Listener> {}; - -INSTANTIATE_TEST_SUITE_P(VariousPadLengths, - HeadersPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256)); - -// Decode various sizes of (fake) HPACK payload, both with and without the -// PRIORITY flag set. -TEST_P(HeadersPayloadDecoderTest, VariousHpackPayloadSizes) { - for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) { - HTTP2_LOG(INFO) << "########### hpack_size = " << hpack_size - << " ###########"; - Http2PriorityFields priority(RandStreamId(), 1 + Random().Rand8(), - Random().OneIn(2)); - - for (bool has_priority : {false, true}) { - Reset(); - ASSERT_EQ(IsPadded() ? 1u : 0u, frame_builder_.size()); - uint8_t flags = RandFlags(); - if (has_priority) { - flags |= Http2FrameFlag::PRIORITY; - frame_builder_.Append(priority); - } - - std::string hpack_payload = Random().RandString(hpack_size); - frame_builder_.Append(hpack_payload); - - MaybeAppendTrailingPadding(); - Http2FrameHeader frame_header(frame_builder_.size(), - Http2FrameType::HEADERS, flags, - RandStreamId()); - set_frame_header(frame_header); - ScrubFlagsOfHeader(&frame_header); - FrameParts expected(frame_header, hpack_payload, total_pad_length_); - if (has_priority) { - expected.SetOptPriority(priority); - } - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), - expected)); - } - } -} - -// Confirm we get an error if the PRIORITY flag is set but the payload is -// not long enough, regardless of the amount of (valid) padding. -TEST_P(HeadersPayloadDecoderTest, Truncated) { - auto approve_size = [](size_t size) { - return size != Http2PriorityFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(Http2PriorityFields(RandStreamId(), 1 + Random().Rand8(), - Random().OneIn(2))); - EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors( - Http2FrameFlag::PRIORITY, fb.buffer(), approve_size, total_pad_length_)); -} - -// Confirm we get an error if the PADDED flag is set but the payload is not -// long enough to hold even the Pad Length amount of padding. -TEST_P(HeadersPayloadDecoderTest, PaddingTooLong) { - EXPECT_TRUE(VerifyDetectsPaddingTooLong()); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc deleted file mode 100644 index a393f4c15fc..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" - -#include "http2/decoder/frame_decoder_state_test_util.h" -#include "http2/http2_structures_test_util.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -PayloadDecoderBaseTest::PayloadDecoderBaseTest() { - // If the test adds more data after the frame payload, - // stop as soon as the payload is decoded. - stop_decode_on_done_ = true; - frame_header_is_set_ = false; - Randomize(&frame_header_, RandomPtr()); -} - -DecodeStatus PayloadDecoderBaseTest::StartDecoding(DecodeBuffer* db) { - HTTP2_DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining(); - // Make sure sub-class has set frame_header_ so that we can inject it - // into the payload decoder below. - if (!frame_header_is_set_) { - ADD_FAILURE() << "frame_header_ is not set"; - return DecodeStatus::kDecodeError; - } - // The contract with the payload decoders is that they won't receive a - // decode buffer that extends beyond the end of the frame. - if (db->Remaining() > frame_header_.payload_length) { - ADD_FAILURE() << "DecodeBuffer has too much data: " << db->Remaining() - << " > " << frame_header_.payload_length; - return DecodeStatus::kDecodeError; - } - - // Prepare the payload decoder. - PreparePayloadDecoder(); - - // Reconstruct the FrameDecoderState, prepare the listener, and add it to - // the FrameDecoderState. - frame_decoder_state_ = std::make_unique<FrameDecoderState>(); - frame_decoder_state_->set_listener(PrepareListener()); - - // Make sure that a listener was provided. - if (frame_decoder_state_->listener() == nullptr) { - ADD_FAILURE() << "PrepareListener must return a listener."; - return DecodeStatus::kDecodeError; - } - - // Now that nothing in the payload decoder should be valid, inject the - // Http2FrameHeader whose payload we're about to decode. That header is the - // only state that a payload decoder should expect is valid when its Start - // method is called. - FrameDecoderStatePeer::set_frame_header(frame_header_, - frame_decoder_state_.get()); - DecodeStatus status = StartDecodingPayload(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++fast_decode_count_; - } - return status; -} - -DecodeStatus PayloadDecoderBaseTest::ResumeDecoding(DecodeBuffer* db) { - HTTP2_DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining(); - DecodeStatus status = ResumeDecodingPayload(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++slow_decode_count_; - } - return status; -} - -::testing::AssertionResult -PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( - absl::string_view payload, - Validator validator) { - VERIFY_TRUE(frame_header_is_set_); - // Cap the payload to be decoded at the declared payload length. This is - // required by the decoders' preconditions; they are designed on the - // assumption that they're never passed more than they're permitted to - // consume. - // Note that it is OK if the payload is too short; the validator may be - // designed to check for that. - if (payload.size() > frame_header_.payload_length) { - payload = absl::string_view(payload.data(), frame_header_.payload_length); - } - DecodeBuffer db(payload); - ResetDecodeSpeedCounters(); - const bool kMayReturnZeroOnFirst = false; - return DecodeAndValidateSeveralWays(&db, kMayReturnZeroOnFirst, validator); -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h deleted file mode 100644 index feea5e5ef0f..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h +++ /dev/null @@ -1,449 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ - -// Base class for testing concrete payload decoder classes. - -#include <stddef.h> - -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_constants_test_util.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" - -namespace http2 { -namespace test { - -// Base class for tests of payload decoders. Below this there is a templated -// sub-class that adds a bunch of type specific features. -class PayloadDecoderBaseTest : public RandomDecoderTest { - protected: - PayloadDecoderBaseTest(); - - // Virtual functions to be implemented by the test classes for the individual - // payload decoders... - - // Start decoding the payload. - virtual DecodeStatus StartDecodingPayload(DecodeBuffer* db) = 0; - - // Resume decoding the payload. - virtual DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) = 0; - - // In support of ensuring that we're really accessing and updating the - // decoder, prepare the decoder by, for example, overwriting the decoder. - virtual void PreparePayloadDecoder() = 0; - - // Get the listener to be inserted into the FrameDecoderState, ready for - // listening (e.g. reset if it is a FramePartsCollector). - virtual Http2FrameDecoderListener* PrepareListener() = 0; - - // Record a frame header for use on each call to StartDecoding. - void set_frame_header(const Http2FrameHeader& header) { - EXPECT_EQ(0, InvalidFlagMaskForFrameType(header.type) & header.flags); - if (!frame_header_is_set_ || frame_header_ != header) { - HTTP2_VLOG(2) << "set_frame_header: " << frame_header_; - } - frame_header_ = header; - frame_header_is_set_ = true; - } - - FrameDecoderState* mutable_state() { return frame_decoder_state_.get(); } - - // Randomize the payload decoder, sets the payload decoder's frame_header_, - // then start decoding the payload. Called by RandomDecoderTest. This method - // is final so that we can always perform certain actions when - // RandomDecoderTest starts the decoding of a payload, such as randomizing the - // the payload decoder, injecting the frame header and counting fast decoding - // cases. Sub-classes must implement StartDecodingPayload to perform their - // initial decoding of a frame's payload. - DecodeStatus StartDecoding(DecodeBuffer* db) final; - - // Called by RandomDecoderTest. This method is final so that we can always - // perform certain actions when RandomDecoderTest calls it, such as counting - // slow decode cases. Sub-classes must implement ResumeDecodingPayload to - // continue decoding the frame's payload, which must not all be in one buffer. - DecodeStatus ResumeDecoding(DecodeBuffer* db) final; - - // Given the specified payload (without the common frame header), decode - // it with several partitionings of the payload. - ::testing::AssertionResult DecodePayloadAndValidateSeveralWays( - absl::string_view payload, - Validator validator); - - // TODO(jamessynge): Add helper method for verifying these are both non-zero, - // and call the new method from tests that expect successful decoding. - void ResetDecodeSpeedCounters() { - fast_decode_count_ = 0; - slow_decode_count_ = 0; - } - - // Count of payloads that are full decoded by StartDecodingPayload, or that - // an error was detected by StartDecodingPayload. - size_t fast_decode_count_ = 0; - - // Count of payloads that require calling ResumeDecodingPayload in order to - // decode them completely (or to detect an error during decoding). - size_t slow_decode_count_ = 0; - - private: - bool frame_header_is_set_ = false; - Http2FrameHeader frame_header_; - std::unique_ptr<FrameDecoderState> frame_decoder_state_; -}; - -// Base class for payload decoders of type Decoder, with corresponding test -// peer of type DecoderPeer, and using class Listener as the implementation -// of Http2FrameDecoderListenerInterface to be used during decoding. -// Typically Listener is a sub-class of FramePartsCollector. -// SupportedFrameType is set to false only for UnknownPayloadDecoder. -template <class Decoder, - class DecoderPeer, - class Listener, - bool SupportedFrameType = true> -class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest { - protected: - // An ApproveSize function returns true to approve decoding the specified - // size of payload, else false to skip that size. Typically used for negative - // tests; for example, decoding a SETTINGS frame at all sizes except for - // multiples of 6. - typedef std::function<bool(size_t size)> ApproveSize; - - AbstractPayloadDecoderTest() {} - - // These tests are in setup rather than the constructor for two reasons: - // 1) Constructors are not allowed to fail, so gUnit documents that EXPECT_* - // and ASSERT_* are not allowed in constructors, and should instead be in - // SetUp if they are needed before the body of the test is executed. - // 2) To allow the sub-class constructor to make any desired modifications to - // the DecoderPeer before these tests are executed; in particular, - // UnknownPayloadDecoderPeer has not got a fixed frame type, but it is - // instead set during the test's constructor. - void SetUp() override { - PayloadDecoderBaseTest::SetUp(); - - // Confirm that DecoderPeer et al returns sensible values. Using auto as the - // variable type so that no (narrowing) conversions take place that hide - // problems; i.e. if someone changes KnownFlagsMaskForFrameType so that it - // doesn't return a uint8, and has bits above the low-order 8 bits set, this - // bit of paranoia should detect the problem before we get too far. - auto frame_type = DecoderPeer::FrameType(); - if (SupportedFrameType) { - EXPECT_TRUE(IsSupportedHttp2FrameType(frame_type)) << frame_type; - } else { - EXPECT_FALSE(IsSupportedHttp2FrameType(frame_type)) << frame_type; - } - - auto known_flags = KnownFlagsMaskForFrameType(frame_type); - EXPECT_EQ(known_flags, known_flags & 0xff); - - auto flags_to_avoid = DecoderPeer::FlagsAffectingPayloadDecoding(); - EXPECT_EQ(flags_to_avoid, flags_to_avoid & known_flags); - } - - void PreparePayloadDecoder() override { - payload_decoder_ = std::make_unique<Decoder>(); - } - - Http2FrameDecoderListener* PrepareListener() override { - listener_.Reset(); - return &listener_; - } - - // Returns random flags, but only those valid for the frame type, yet not - // those that the DecoderPeer says will affect the decoding of the payload - // (e.g. the PRIORTY flag on a HEADERS frame or PADDED on DATA frames). - uint8_t RandFlags() { - return Random().Rand8() & - KnownFlagsMaskForFrameType(DecoderPeer::FrameType()) & - ~DecoderPeer::FlagsAffectingPayloadDecoding(); - } - - // Start decoding the payload. - DecodeStatus StartDecodingPayload(DecodeBuffer* db) override { - HTTP2_DVLOG(2) << "StartDecodingPayload, db->Remaining=" << db->Remaining(); - return payload_decoder_->StartDecodingPayload(mutable_state(), db); - } - - // Resume decoding the payload. - DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) override { - HTTP2_DVLOG(2) << "ResumeDecodingPayload, db->Remaining=" - << db->Remaining(); - return payload_decoder_->ResumeDecodingPayload(mutable_state(), db); - } - - // Decode one frame's payload and confirm that the listener recorded the - // expected FrameParts instance, and only FrameParts instance. The payload - // will be decoded several times with different partitionings of the payload, - // and after each the validator will be called. - AssertionResult DecodePayloadAndValidateSeveralWays( - absl::string_view payload, - const FrameParts& expected) { - auto validator = [&expected, this]() -> AssertionResult { - VERIFY_FALSE(listener_.IsInProgress()); - VERIFY_EQ(1u, listener_.size()); - VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0))); - }; - return PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( - payload, ValidateDoneAndEmpty(validator)); - } - - // Decode one frame's payload, expecting that the final status will be - // kDecodeError, and that OnFrameSizeError will have been called on the - // listener. The payload will be decoded several times with different - // partitionings of the payload. The type WrappedValidator is either - // RandomDecoderTest::Validator, RandomDecoderTest::NoArgValidator or - // std::nullptr_t (not extra validation). - template <typename WrappedValidator> - ::testing::AssertionResult VerifyDetectsFrameSizeError( - absl::string_view payload, - const Http2FrameHeader& header, - WrappedValidator wrapped_validator) { - set_frame_header(header); - // If wrapped_validator is not a RandomDecoderTest::Validator, make it so. - Validator validator = ToValidator(wrapped_validator); - // And wrap that validator in another which will check that we've reached - // the expected state of kDecodeError with OnFrameSizeError having been - // called by the payload decoder. - validator = [header, validator, this]( - const DecodeBuffer& input, - DecodeStatus status) -> ::testing::AssertionResult { - HTTP2_DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" - << status << "; input.Remaining=" << input.Remaining(); - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_FALSE(listener_.IsInProgress()); - VERIFY_EQ(1u, listener_.size()); - const FrameParts* frame = listener_.frame(0); - VERIFY_EQ(header, frame->GetFrameHeader()); - VERIFY_TRUE(frame->GetHasFrameSizeError()); - // Verify did not get OnPaddingTooLong, as we should only ever produce - // one of these two errors for a single frame. - VERIFY_FALSE(frame->GetOptMissingLength()); - return validator(input, status); - }; - VERIFY_AND_RETURN_SUCCESS( - PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload, - validator)); - } - - // Confirm that we get OnFrameSizeError when trying to decode unpadded_payload - // at all sizes from zero to unpadded_payload.size(), except those sizes not - // approved by approve_size. - // If total_pad_length is greater than zero, then that amount of padding - // is added to the payload (including the Pad Length field). - // The flags will be required_flags, PADDED if total_pad_length > 0, and some - // randomly selected flag bits not excluded by FlagsAffectingPayloadDecoding. - ::testing::AssertionResult VerifyDetectsMultipleFrameSizeErrors( - uint8_t required_flags, - absl::string_view unpadded_payload, - ApproveSize approve_size, - int total_pad_length) { - // required_flags should come from those that are defined for the frame - // type AND are those that affect the decoding of the payload (otherwise, - // the flag shouldn't be required). - Http2FrameType frame_type = DecoderPeer::FrameType(); - VERIFY_EQ(required_flags, - required_flags & KnownFlagsMaskForFrameType(frame_type)); - VERIFY_EQ(required_flags, - required_flags & DecoderPeer::FlagsAffectingPayloadDecoding()); - - if (0 != - (Http2FrameFlag::PADDED & KnownFlagsMaskForFrameType(frame_type))) { - // Frame type supports padding. - if (total_pad_length == 0) { - required_flags &= ~Http2FrameFlag::PADDED; - } else { - required_flags |= Http2FrameFlag::PADDED; - } - } else { - VERIFY_EQ(0, total_pad_length); - } - - bool validated = false; - for (size_t real_payload_size = 0; - real_payload_size <= unpadded_payload.size(); ++real_payload_size) { - if (approve_size != nullptr && !approve_size(real_payload_size)) { - continue; - } - HTTP2_VLOG(1) << "real_payload_size=" << real_payload_size; - uint8_t flags = required_flags | RandFlags(); - Http2FrameBuilder fb; - if (total_pad_length > 0) { - // total_pad_length_ includes the size of the Pad Length field, and thus - // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). - fb.AppendUInt8(total_pad_length - 1); - } - // Append a subset of the unpadded_payload, which the decoder should - // determine is not a valid amount. - fb.Append(unpadded_payload.substr(0, real_payload_size)); - if (total_pad_length > 0) { - fb.AppendZeroes(total_pad_length - 1); - } - // We choose a random stream id because the payload decoders aren't - // checking stream ids. - uint32_t stream_id = RandStreamId(); - Http2FrameHeader header(fb.size(), frame_type, flags, stream_id); - VERIFY_SUCCESS(VerifyDetectsFrameSizeError(fb.buffer(), header, nullptr)); - validated = true; - } - VERIFY_TRUE(validated); - return ::testing::AssertionSuccess(); - } - - // As above, but for frames without padding. - ::testing::AssertionResult VerifyDetectsFrameSizeError( - uint8_t required_flags, - absl::string_view unpadded_payload, - const ApproveSize& approve_size) { - Http2FrameType frame_type = DecoderPeer::FrameType(); - uint8_t known_flags = KnownFlagsMaskForFrameType(frame_type); - VERIFY_EQ(0, known_flags & Http2FrameFlag::PADDED); - VERIFY_EQ(0, required_flags & Http2FrameFlag::PADDED); - VERIFY_AND_RETURN_SUCCESS(VerifyDetectsMultipleFrameSizeErrors( - required_flags, unpadded_payload, approve_size, 0)); - } - - Listener listener_; - std::unique_ptr<Decoder> payload_decoder_; -}; - -// A base class for tests parameterized by the total number of bytes of -// padding, including the Pad Length field (i.e. a total_pad_length of 0 -// means unpadded as there is then no room for the Pad Length field). -// The frame type must support padding. -template <class Decoder, class DecoderPeer, class Listener> -class AbstractPaddablePayloadDecoderTest - : public AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener>, - public ::testing::WithParamInterface<int> { - typedef AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener> Base; - - protected: - using Base::listener_; - using Base::Random; - using Base::RandStreamId; - using Base::set_frame_header; - typedef typename Base::Validator Validator; - - AbstractPaddablePayloadDecoderTest() : total_pad_length_(GetParam()) { - HTTP2_LOG(INFO) << "total_pad_length_ = " << total_pad_length_; - } - - // Note that total_pad_length_ includes the size of the Pad Length field, - // and thus ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). - bool IsPadded() const { return total_pad_length_ > 0; } - - // Value of the Pad Length field. Only call if IsPadded. - size_t pad_length() const { - EXPECT_TRUE(IsPadded()); - return total_pad_length_ - 1; - } - - // Clear the frame builder and add the Pad Length field if appropriate. - void Reset() { - frame_builder_ = Http2FrameBuilder(); - if (IsPadded()) { - frame_builder_.AppendUInt8(pad_length()); - } - } - - void MaybeAppendTrailingPadding() { - if (IsPadded()) { - frame_builder_.AppendZeroes(pad_length()); - } - } - - uint8_t RandFlags() { - uint8_t flags = Base::RandFlags(); - if (IsPadded()) { - flags |= Http2FrameFlag::PADDED; - } else { - flags &= ~Http2FrameFlag::PADDED; - } - return flags; - } - - // Verify that we get OnPaddingTooLong when decoding payload, and that the - // amount of missing padding is as specified. header.IsPadded must be true, - // and the payload must be empty or the PadLength field must be too large. - ::testing::AssertionResult VerifyDetectsPaddingTooLong( - absl::string_view payload, - const Http2FrameHeader& header, - size_t expected_missing_length) { - set_frame_header(header); - auto& listener = listener_; - Validator validator = - [header, expected_missing_length, &listener]( - const DecodeBuffer&, - DecodeStatus status) -> ::testing::AssertionResult { - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_FALSE(listener.IsInProgress()); - VERIFY_EQ(1u, listener.size()); - const FrameParts* frame = listener.frame(0); - VERIFY_EQ(header, frame->GetFrameHeader()); - VERIFY_TRUE(frame->GetOptMissingLength()); - VERIFY_EQ(expected_missing_length, frame->GetOptMissingLength().value()); - // Verify did not get OnFrameSizeError. - VERIFY_FALSE(frame->GetHasFrameSizeError()); - return ::testing::AssertionSuccess(); - }; - VERIFY_AND_RETURN_SUCCESS( - PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload, - validator)); - } - - // Verifies that we get OnPaddingTooLong for a padded frame payload whose - // (randomly selected) payload length is less than total_pad_length_. - // Flags will be selected at random, except PADDED will be set and - // flags_to_avoid will not be set. The stream id is selected at random. - ::testing::AssertionResult VerifyDetectsPaddingTooLong() { - uint8_t flags = RandFlags() | Http2FrameFlag::PADDED; - - // Create an all padding payload for total_pad_length_. - int payload_length = 0; - Http2FrameBuilder fb; - if (IsPadded()) { - fb.AppendUInt8(pad_length()); - fb.AppendZeroes(pad_length()); - HTTP2_VLOG(1) << "fb.size=" << fb.size(); - // Pick a random length for the payload that is shorter than neccesary. - payload_length = Random().Uniform(fb.size()); - } - - HTTP2_VLOG(1) << "payload_length=" << payload_length; - std::string payload = fb.buffer().substr(0, payload_length); - - // The missing length is the amount we cut off the end, unless - // payload_length is zero, in which case the decoder knows only that 1 - // byte, the Pad Length field, is missing. - size_t missing_length = - payload_length == 0 ? 1 : fb.size() - payload_length; - HTTP2_VLOG(1) << "missing_length=" << missing_length; - - const Http2FrameHeader header(payload_length, DecoderPeer::FrameType(), - flags, RandStreamId()); - VERIFY_AND_RETURN_SUCCESS( - VerifyDetectsPaddingTooLong(payload, header, missing_length)); - } - - // total_pad_length_ includes the size of the Pad Length field, and thus - // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). - const size_t total_pad_length_; - Http2FrameBuilder frame_builder_; -}; - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.cc deleted file mode 100644 index 6c73cf781e0..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/ping_payload_decoder.h" - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { -namespace { -constexpr auto kOpaqueSize = Http2PingFields::EncodedSize(); -} - -DecodeStatus PingPayloadDecoder::StartDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - HTTP2_DVLOG(2) << "PingPayloadDecoder::StartDecodingPayload: " - << frame_header; - QUICHE_DCHECK_EQ(Http2FrameType::PING, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), total_length); - QUICHE_DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::ACK)); - - // Is the payload entirely in the decode buffer and is it the correct size? - // Given the size of the header and payload (17 bytes total), this is most - // likely the case the vast majority of the time. - if (db->Remaining() == kOpaqueSize && total_length == kOpaqueSize) { - // Special case this situation as it allows us to avoid any copying; - // the other path makes two copies, first into the buffer in - // Http2StructureDecoder as it accumulates the 8 bytes of opaque data, - // and a second copy into the Http2PingFields member of in this class. - // This supports the claim that this decoder is (mostly) non-buffering. - static_assert(sizeof(Http2PingFields) == kOpaqueSize, - "If not, then can't enter this block!"); - auto* ping = reinterpret_cast<const Http2PingFields*>(db->cursor()); - if (frame_header.IsAck()) { - state->listener()->OnPingAck(frame_header, *ping); - } else { - state->listener()->OnPing(frame_header, *ping); - } - db->AdvanceCursor(kOpaqueSize); - return DecodeStatus::kDecodeDone; - } - state->InitializeRemainders(); - return HandleStatus( - state, state->StartDecodingStructureInPayload(&ping_fields_, db)); -} - -DecodeStatus PingPayloadDecoder::ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "ResumeDecodingPayload: remaining_payload=" - << state->remaining_payload(); - QUICHE_DCHECK_EQ(Http2FrameType::PING, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus( - state, state->ResumeDecodingStructureInPayload(&ping_fields_, db)); -} - -DecodeStatus PingPayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - HTTP2_DVLOG(2) << "HandleStatus: status=" << status - << "; remaining_payload=" << state->remaining_payload(); - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - const Http2FrameHeader& frame_header = state->frame_header(); - if (frame_header.IsAck()) { - state->listener()->OnPingAck(frame_header, ping_fields_); - } else { - state->listener()->OnPing(frame_header, ping_fields_); - } - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short. - QUICHE_DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.h deleted file mode 100644 index d6d2b7d75a1..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_ - -// Decodes the payload of a PING frame; for the RFC, see: -// http://httpwg.org/specs/rfc7540.html#PING - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class PingPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE PingPayloadDecoder { - public: - // Starts the decoding of a PING frame's payload, and completes it if the - // entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a PING frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::PingPayloadDecoderPeer; - - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2PingFields ping_fields_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder_test.cc deleted file mode 100644 index 7f310a8d987..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder_test.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/ping_payload_decoder.h" - -#include <stddef.h> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class PingPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::PING; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override { - HTTP2_VLOG(1) << "OnPing: " << header << "; " << ping; - StartAndEndFrame(header)->OnPing(header, ping); - } - - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override { - HTTP2_VLOG(1) << "OnPingAck: " << header << "; " << ping; - StartAndEndFrame(header)->OnPingAck(header, ping); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class PingPayloadDecoderTest - : public AbstractPayloadDecoderTest<PingPayloadDecoder, - PingPayloadDecoderPeer, - Listener> { - protected: - Http2PingFields RandPingFields() { - Http2PingFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2PingFields. -TEST_F(PingPayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2PingFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandPingFields()); - fb.Append(RandPingFields()); - fb.Append(RandPingFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(PingPayloadDecoderTest, Ping) { - for (int n = 0; n < 100; ++n) { - Http2PingFields fields = RandPingFields(); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::PING, - RandFlags() & ~Http2FrameFlag::ACK, RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptPing(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -TEST_F(PingPayloadDecoderTest, PingAck) { - for (int n = 0; n < 100; ++n) { - Http2PingFields fields; - Randomize(&fields, RandomPtr()); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::PING, - RandFlags() | Http2FrameFlag::ACK, RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptPing(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.cc deleted file mode 100644 index e68cbcebaf4..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/priority_payload_decoder.h" - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -DecodeStatus PriorityPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "PriorityPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::PRIORITY, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - // PRIORITY frames have no flags. - QUICHE_DCHECK_EQ(0, state->frame_header().flags); - state->InitializeRemainders(); - return HandleStatus( - state, state->StartDecodingStructureInPayload(&priority_fields_, db)); -} - -DecodeStatus PriorityPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "PriorityPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - QUICHE_DCHECK_EQ(Http2FrameType::PRIORITY, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus( - state, state->ResumeDecodingStructureInPayload(&priority_fields_, db)); -} - -DecodeStatus PriorityPayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - state->listener()->OnPriorityFrame(state->frame_header(), - priority_fields_); - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called. - QUICHE_DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.h deleted file mode 100644 index 7e6a9eeeebe..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_ - -// Decodes the payload of a PRIORITY frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class PriorityPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE PriorityPayloadDecoder { - public: - // Starts the decoding of a PRIORITY frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a PRIORITY frame that has been split across decode - // buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::PriorityPayloadDecoderPeer; - - // Determines whether to report the PRIORITY to the listener, wait for more - // input, or to report a Frame Size Error. - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2PriorityFields priority_fields_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder_test.cc deleted file mode 100644 index 08c9ec0b85b..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder_test.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/priority_payload_decoder.h" - -#include <stddef.h> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class PriorityPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::PRIORITY; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority_fields) override { - HTTP2_VLOG(1) << "OnPriority: " << header << "; " << priority_fields; - StartAndEndFrame(header)->OnPriorityFrame(header, priority_fields); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class PriorityPayloadDecoderTest - : public AbstractPayloadDecoderTest<PriorityPayloadDecoder, - PriorityPayloadDecoderPeer, - Listener> { - protected: - Http2PriorityFields RandPriorityFields() { - Http2PriorityFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2PriorityFields. -TEST_F(PriorityPayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2PriorityFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandPriorityFields()); - fb.Append(RandPriorityFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(PriorityPayloadDecoderTest, VariousPayloads) { - for (int n = 0; n < 100; ++n) { - Http2PriorityFields fields = RandPriorityFields(); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::PRIORITY, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptPriority(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc deleted file mode 100644 index ff6758c3729..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/priority_update_payload_decoder.h" - -#include <stddef.h> - -#include "absl/base/macros.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - PriorityUpdatePayloadDecoder::PayloadState v) { - switch (v) { - case PriorityUpdatePayloadDecoder::PayloadState::kStartDecodingFixedFields: - return out << "kStartDecodingFixedFields"; - case PriorityUpdatePayloadDecoder::PayloadState::kResumeDecodingFixedFields: - return out << "kResumeDecodingFixedFields"; - case PriorityUpdatePayloadDecoder::PayloadState::kHandleFixedFieldsStatus: - return out << "kHandleFixedFieldsStatus"; - case PriorityUpdatePayloadDecoder::PayloadState::kReadPriorityFieldValue: - return out << "kReadPriorityFieldValue"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG(http2_bug_173_1) - << "Invalid PriorityUpdatePayloadDecoder::PayloadState: " << unknown; - return out << "PriorityUpdatePayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus PriorityUpdatePayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "PriorityUpdatePayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::PRIORITY_UPDATE, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - QUICHE_DCHECK_EQ(0, state->frame_header().flags); - - state->InitializeRemainders(); - payload_state_ = PayloadState::kStartDecodingFixedFields; - return ResumeDecodingPayload(state, db); -} - -DecodeStatus PriorityUpdatePayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "PriorityUpdatePayloadDecoder::ResumeDecodingPayload: " - "remaining_payload=" - << state->remaining_payload() - << ", db->Remaining=" << db->Remaining(); - - const Http2FrameHeader& frame_header = state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::PRIORITY_UPDATE, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), frame_header.payload_length); - QUICHE_DCHECK_NE(PayloadState::kHandleFixedFieldsStatus, payload_state_); - - // |status| has to be initialized to some value to avoid compiler error in - // case PayloadState::kHandleFixedFieldsStatus below, but value does not - // matter, see QUICHE_DCHECK_NE above. - DecodeStatus status = DecodeStatus::kDecodeError; - size_t avail; - while (true) { - HTTP2_DVLOG(2) - << "PriorityUpdatePayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kStartDecodingFixedFields: - status = state->StartDecodingStructureInPayload( - &priority_update_fields_, db); - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kHandleFixedFieldsStatus: - if (status == DecodeStatus::kDecodeDone) { - state->listener()->OnPriorityUpdateStart(frame_header, - priority_update_fields_); - } else { - // Not done decoding the structure. Either we've got more payload - // to decode, or we've run out because the payload is too short, - // in which case OnFrameSizeError will have already been called. - QUICHE_DCHECK((status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && - state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - payload_state_ = PayloadState::kResumeDecodingFixedFields; - return status; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kReadPriorityFieldValue: - // Anything left in the decode buffer is the Priority Field Value. - avail = db->Remaining(); - if (avail > 0) { - state->listener()->OnPriorityUpdatePayload(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadPriorityFieldValue; - return DecodeStatus::kDecodeInProgress; - } - state->listener()->OnPriorityUpdateEnd(); - return DecodeStatus::kDecodeDone; - - case PayloadState::kResumeDecodingFixedFields: - status = state->ResumeDecodingStructureInPayload( - &priority_update_fields_, db); - payload_state_ = PayloadState::kHandleFixedFieldsStatus; - continue; - } - HTTP2_BUG(http2_bug_173_2) << "PayloadState: " << payload_state_; - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.h deleted file mode 100644 index f2557b2661a..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_UPDATE_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_UPDATE_PAYLOAD_DECODER_H_ - -// Decodes the payload of a PRIORITY_UPDATE frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class PriorityUpdatePayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE PriorityUpdatePayloadDecoder { - public: - // States during decoding of a PRIORITY_UPDATE frame. - enum class PayloadState { - // At the start of the PRIORITY_UPDATE frame payload, ready to start - // decoding the fixed size fields into priority_update_fields_. - kStartDecodingFixedFields, - - // The fixed size fields weren't all available when the decoder first - // tried to decode them; this state resumes the decoding when - // ResumeDecodingPayload is called later. - kResumeDecodingFixedFields, - - // Handle the DecodeStatus returned from starting or resuming the decoding - // of Http2PriorityUpdateFields into priority_update_fields_. If complete, - // calls OnPriorityUpdateStart. - kHandleFixedFieldsStatus, - - // Report the Priority Field Value portion of the payload to the listener's - // OnPriorityUpdatePayload method, and call OnPriorityUpdateEnd when the end - // of the payload is reached. - kReadPriorityFieldValue, - }; - - // Starts the decoding of a PRIORITY_UPDATE frame's payload, and completes it - // if the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a PRIORITY_UPDATE frame that has been split across decode - // buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::PriorityUpdatePayloadDecoderPeer; - - Http2PriorityUpdateFields priority_update_fields_; - PayloadState payload_state_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_UPDATE_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc deleted file mode 100644 index 41b7dc85bce..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/priority_update_payload_decoder.h" - -#include <stddef.h> - -#include <string> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class PriorityUpdatePayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::PRIORITY_UPDATE; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnPriorityUpdateStart( - const Http2FrameHeader& header, - const Http2PriorityUpdateFields& priority_update) override { - HTTP2_VLOG(1) << "OnPriorityUpdateStart header: " << header - << "; priority_update: " << priority_update; - StartFrame(header)->OnPriorityUpdateStart(header, priority_update); - } - - void OnPriorityUpdatePayload(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnPriorityUpdatePayload: len=" << len; - CurrentFrame()->OnPriorityUpdatePayload(data, len); - } - - void OnPriorityUpdateEnd() override { - HTTP2_VLOG(1) << "OnPriorityUpdateEnd"; - EndFrame()->OnPriorityUpdateEnd(); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class PriorityUpdatePayloadDecoderTest - : public AbstractPayloadDecoderTest<PriorityUpdatePayloadDecoder, - PriorityUpdatePayloadDecoderPeer, - Listener> {}; - -// Confirm we get an error if the payload is not long enough to hold -// Http2PriorityUpdateFields. -TEST_F(PriorityUpdatePayloadDecoderTest, Truncated) { - auto approve_size = [](size_t size) { - return size != Http2PriorityUpdateFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(Http2PriorityUpdateFields(123)); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -class PriorityUpdatePayloadLengthTests - : public AbstractPayloadDecoderTest<PriorityUpdatePayloadDecoder, - PriorityUpdatePayloadDecoderPeer, - Listener>, - public ::testing::WithParamInterface<uint32_t> { - protected: - PriorityUpdatePayloadLengthTests() : length_(GetParam()) { - HTTP2_VLOG(1) << "################ length_=" << length_ - << " ################"; - } - - const uint32_t length_; -}; - -INSTANTIATE_TEST_SUITE_P(VariousLengths, - PriorityUpdatePayloadLengthTests, - ::testing::Values(0, 1, 2, 3, 4, 5, 6)); - -TEST_P(PriorityUpdatePayloadLengthTests, ValidLength) { - Http2PriorityUpdateFields priority_update; - Randomize(&priority_update, RandomPtr()); - std::string priority_field_value = Random().RandString(length_); - Http2FrameBuilder fb; - fb.Append(priority_update); - fb.Append(priority_field_value); - Http2FrameHeader header(fb.size(), Http2FrameType::PRIORITY_UPDATE, - RandFlags(), RandStreamId()); - set_frame_header(header); - FrameParts expected(header, priority_field_value); - expected.SetOptPriorityUpdate(Http2PriorityUpdateFields{priority_update}); - ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc deleted file mode 100644 index 8dff0b9fe38..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/push_promise_payload_decoder.h" - -#include <stddef.h> - -#include "absl/base/macros.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - PushPromisePayloadDecoder::PayloadState v) { - switch (v) { - case PushPromisePayloadDecoder::PayloadState::kReadPadLength: - return out << "kReadPadLength"; - case PushPromisePayloadDecoder::PayloadState:: - kStartDecodingPushPromiseFields: - return out << "kStartDecodingPushPromiseFields"; - case PushPromisePayloadDecoder::PayloadState::kReadPayload: - return out << "kReadPayload"; - case PushPromisePayloadDecoder::PayloadState::kSkipPadding: - return out << "kSkipPadding"; - case PushPromisePayloadDecoder::PayloadState:: - kResumeDecodingPushPromiseFields: - return out << "kResumeDecodingPushPromiseFields"; - } - return out << static_cast<int>(v); -} - -DecodeStatus PushPromisePayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - HTTP2_DVLOG(2) << "PushPromisePayloadDecoder::StartDecodingPayload: " - << frame_header; - - QUICHE_DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), total_length); - QUICHE_DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED)); - - if (!frame_header.IsPadded()) { - // If it turns out that PUSH_PROMISE frames without padding are sufficiently - // common, and that they are usually short enough that they fit entirely - // into one DecodeBuffer, we can detect that here and implement a special - // case, avoiding the state machine in ResumeDecodingPayload. - payload_state_ = PayloadState::kStartDecodingPushPromiseFields; - } else { - payload_state_ = PayloadState::kReadPadLength; - } - state->InitializeRemainders(); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus PushPromisePayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "UnknownPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - - const Http2FrameHeader& frame_header = state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type); - QUICHE_DCHECK_LE(state->remaining_payload(), frame_header.payload_length); - QUICHE_DCHECK_LE(db->Remaining(), frame_header.payload_length); - - DecodeStatus status; - while (true) { - HTTP2_DVLOG(2) - << "PushPromisePayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kReadPadLength: - QUICHE_DCHECK_EQ(state->remaining_payload(), - frame_header.payload_length); - // ReadPadLength handles the OnPadLength callback, and updating the - // remaining_payload and remaining_padding fields. If the amount of - // padding is too large to fit in the frame's payload, ReadPadLength - // instead calls OnPaddingTooLong and returns kDecodeError. - // Suppress the call to OnPadLength because we haven't yet called - // OnPushPromiseStart, which needs to wait until we've decoded the - // Promised Stream ID. - status = state->ReadPadLength(db, /*report_pad_length*/ false); - if (status != DecodeStatus::kDecodeDone) { - payload_state_ = PayloadState::kReadPadLength; - return status; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kStartDecodingPushPromiseFields: - status = - state->StartDecodingStructureInPayload(&push_promise_fields_, db); - if (status != DecodeStatus::kDecodeDone) { - payload_state_ = PayloadState::kResumeDecodingPushPromiseFields; - return status; - } - // Finished decoding the Promised Stream ID. Can now tell the listener - // that we're starting to decode a PUSH_PROMISE frame. - ReportPushPromise(state); - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kReadPayload: - QUICHE_DCHECK_LT(state->remaining_payload(), - frame_header.payload_length); - QUICHE_DCHECK_LE(state->remaining_payload(), - frame_header.payload_length - - Http2PushPromiseFields::EncodedSize()); - QUICHE_DCHECK_LE( - state->remaining_payload(), - frame_header.payload_length - - Http2PushPromiseFields::EncodedSize() - - (frame_header.IsPadded() ? (1 + state->remaining_padding()) - : 0)); - { - size_t avail = state->AvailablePayload(db); - state->listener()->OnHpackFragment(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadPayload; - return DecodeStatus::kDecodeInProgress; - } - ABSL_FALLTHROUGH_INTENDED; - - case PayloadState::kSkipPadding: - // SkipPadding handles the OnPadding callback. - if (state->SkipPadding(db)) { - state->listener()->OnPushPromiseEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kSkipPadding; - return DecodeStatus::kDecodeInProgress; - - case PayloadState::kResumeDecodingPushPromiseFields: - status = - state->ResumeDecodingStructureInPayload(&push_promise_fields_, db); - if (status == DecodeStatus::kDecodeDone) { - // Finished decoding the Promised Stream ID. Can now tell the listener - // that we're starting to decode a PUSH_PROMISE frame. - ReportPushPromise(state); - payload_state_ = PayloadState::kReadPayload; - continue; - } - payload_state_ = PayloadState::kResumeDecodingPushPromiseFields; - return status; - } - HTTP2_BUG(http2_bug_183_1) << "PayloadState: " << payload_state_; - } -} - -void PushPromisePayloadDecoder::ReportPushPromise(FrameDecoderState* state) { - const Http2FrameHeader& frame_header = state->frame_header(); - if (frame_header.IsPadded()) { - state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_, - 1 + state->remaining_padding()); - } else { - state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_, - 0); - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.h deleted file mode 100644 index 7c5b6a2b1c1..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_ - -// Decodes the payload of a PUSH_PROMISE frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class PushPromisePayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE PushPromisePayloadDecoder { - public: - // States during decoding of a PUSH_PROMISE frame. - enum class PayloadState { - // The frame is padded and we need to read the PAD_LENGTH field (1 byte). - kReadPadLength, - - // Ready to start decoding the fixed size fields of the PUSH_PROMISE - // frame into push_promise_fields_. - kStartDecodingPushPromiseFields, - - // The decoder has already called OnPushPromiseStart, and is now reporting - // the HPACK block fragment to the listener's OnHpackFragment method. - kReadPayload, - - // The decoder has finished with the HPACK block fragment, and is now - // ready to skip the trailing padding, if the frame has any. - kSkipPadding, - - // The fixed size fields weren't all available when the decoder first tried - // to decode them (state kStartDecodingPushPromiseFields); this state - // resumes the decoding when ResumeDecodingPayload is called later. - kResumeDecodingPushPromiseFields, - }; - - // Starts the decoding of a PUSH_PROMISE frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a PUSH_PROMISE frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::PushPromisePayloadDecoderPeer; - - void ReportPushPromise(FrameDecoderState* state); - - PayloadState payload_state_; - Http2PushPromiseFields push_promise_fields_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc deleted file mode 100644 index bd784ed521e..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/push_promise_payload_decoder.h" - -#include <stddef.h> - -#include <string> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class PushPromisePayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::PUSH_PROMISE; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::PADDED; - } -}; - -namespace { - -// Listener listens for only those methods expected by the payload decoder -// under test, and forwards them onto the FrameParts instance for the current -// frame. -struct Listener : public FramePartsCollector { - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override { - HTTP2_VLOG(1) << "OnPushPromiseStart header: " << header - << " promise: " << promise - << " total_padding_length: " << total_padding_length; - EXPECT_EQ(Http2FrameType::PUSH_PROMISE, header.type); - StartFrame(header)->OnPushPromiseStart(header, promise, - total_padding_length); - } - - void OnHpackFragment(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnHpackFragment: len=" << len; - CurrentFrame()->OnHpackFragment(data, len); - } - - void OnPushPromiseEnd() override { - HTTP2_VLOG(1) << "OnPushPromiseEnd"; - EndFrame()->OnPushPromiseEnd(); - } - - void OnPadding(const char* padding, size_t skipped_length) override { - HTTP2_VLOG(1) << "OnPadding: " << skipped_length; - CurrentFrame()->OnPadding(padding, skipped_length); - } - - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override { - HTTP2_VLOG(1) << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; - FrameError(header)->OnPaddingTooLong(header, missing_length); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class PushPromisePayloadDecoderTest - : public AbstractPaddablePayloadDecoderTest<PushPromisePayloadDecoder, - PushPromisePayloadDecoderPeer, - Listener> {}; - -INSTANTIATE_TEST_SUITE_P(VariousPadLengths, - PushPromisePayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256)); - -// Payload contains the required Http2PushPromiseFields, followed by some -// (fake) HPACK payload. -TEST_P(PushPromisePayloadDecoderTest, VariousHpackPayloadSizes) { - for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) { - HTTP2_LOG(INFO) << "########### hpack_size = " << hpack_size - << " ###########"; - Reset(); - std::string hpack_payload = Random().RandString(hpack_size); - Http2PushPromiseFields push_promise{RandStreamId()}; - frame_builder_.Append(push_promise); - frame_builder_.Append(hpack_payload); - MaybeAppendTrailingPadding(); - Http2FrameHeader frame_header(frame_builder_.size(), - Http2FrameType::PUSH_PROMISE, RandFlags(), - RandStreamId()); - set_frame_header(frame_header); - FrameParts expected(frame_header, hpack_payload, total_pad_length_); - expected.SetOptPushPromise(push_promise); - EXPECT_TRUE( - DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected)); - } -} - -// Confirm we get an error if the payload is not long enough for the required -// portion of the payload, regardless of the amount of (valid) padding. -TEST_P(PushPromisePayloadDecoderTest, Truncated) { - auto approve_size = [](size_t size) { - return size != Http2PushPromiseFields::EncodedSize(); - }; - Http2PushPromiseFields push_promise{RandStreamId()}; - Http2FrameBuilder fb; - fb.Append(push_promise); - EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(0, fb.buffer(), approve_size, - total_pad_length_)); -} - -// Confirm we get an error if the PADDED flag is set but the payload is not -// long enough to hold even the Pad Length amount of padding. -TEST_P(PushPromisePayloadDecoderTest, PaddingTooLong) { - EXPECT_TRUE(VerifyDetectsPaddingTooLong()); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc deleted file mode 100644 index b2afc406377..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/rst_stream_payload_decoder.h" - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -DecodeStatus RstStreamPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "RstStreamPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - QUICHE_DCHECK_EQ(Http2FrameType::RST_STREAM, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - // RST_STREAM has no flags. - QUICHE_DCHECK_EQ(0, state->frame_header().flags); - state->InitializeRemainders(); - return HandleStatus( - state, state->StartDecodingStructureInPayload(&rst_stream_fields_, db)); -} - -DecodeStatus RstStreamPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "RstStreamPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - QUICHE_DCHECK_EQ(Http2FrameType::RST_STREAM, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus( - state, state->ResumeDecodingStructureInPayload(&rst_stream_fields_, db)); -} - -DecodeStatus RstStreamPayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - HTTP2_DVLOG(2) << "HandleStatus: status=" << status - << "; remaining_payload=" << state->remaining_payload(); - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - state->listener()->OnRstStream(state->frame_header(), - rst_stream_fields_.error_code); - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called by the FrameDecoderState. - QUICHE_DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.h deleted file mode 100644 index 61035c183bd..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_ - -// Decodes the payload of a RST_STREAM frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class RstStreamPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE RstStreamPayloadDecoder { - public: - // Starts the decoding of a RST_STREAM frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a RST_STREAM frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::RstStreamPayloadDecoderPeer; - - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2RstStreamFields rst_stream_fields_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc deleted file mode 100644 index 6299a2c9e9c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/rst_stream_payload_decoder.h" - -#include <stddef.h> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_constants_test_util.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class RstStreamPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::RST_STREAM; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override { - HTTP2_VLOG(1) << "OnRstStream: " << header << "; error_code=" << error_code; - StartAndEndFrame(header)->OnRstStream(header, error_code); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class RstStreamPayloadDecoderTest - : public AbstractPayloadDecoderTest<RstStreamPayloadDecoder, - RstStreamPayloadDecoderPeer, - Listener> { - protected: - Http2RstStreamFields RandRstStreamFields() { - Http2RstStreamFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2RstStreamFields. -TEST_F(RstStreamPayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2RstStreamFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandRstStreamFields()); - fb.Append(RandRstStreamFields()); - fb.Append(RandRstStreamFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(RstStreamPayloadDecoderTest, AllErrors) { - for (auto error_code : AllHttp2ErrorCodes()) { - Http2RstStreamFields fields{error_code}; - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::RST_STREAM, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptRstStreamErrorCode(error_code); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.cc deleted file mode 100644 index a0417928867..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.cc +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/settings_payload_decoder.h" - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -DecodeStatus SettingsPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - HTTP2_DVLOG(2) << "SettingsPayloadDecoder::StartDecodingPayload: " - << frame_header; - QUICHE_DCHECK_EQ(Http2FrameType::SETTINGS, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), total_length); - QUICHE_DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::ACK)); - - if (frame_header.IsAck()) { - if (total_length == 0) { - state->listener()->OnSettingsAck(frame_header); - return DecodeStatus::kDecodeDone; - } else { - state->InitializeRemainders(); - return state->ReportFrameSizeError(); - } - } else { - state->InitializeRemainders(); - state->listener()->OnSettingsStart(frame_header); - return StartDecodingSettings(state, db); - } -} - -DecodeStatus SettingsPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "SettingsPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - QUICHE_DCHECK_EQ(Http2FrameType::SETTINGS, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - - DecodeStatus status = - state->ResumeDecodingStructureInPayload(&setting_fields_, db); - if (status == DecodeStatus::kDecodeDone) { - state->listener()->OnSetting(setting_fields_); - return StartDecodingSettings(state, db); - } - return HandleNotDone(state, db, status); -} - -DecodeStatus SettingsPayloadDecoder::StartDecodingSettings( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "SettingsPayloadDecoder::StartDecodingSettings" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - while (state->remaining_payload() > 0) { - DecodeStatus status = - state->StartDecodingStructureInPayload(&setting_fields_, db); - if (status == DecodeStatus::kDecodeDone) { - state->listener()->OnSetting(setting_fields_); - continue; - } - return HandleNotDone(state, db, status); - } - HTTP2_DVLOG(2) << "LEAVING SettingsPayloadDecoder::StartDecodingSettings" - << "\n\tdb->Remaining=" << db->Remaining() - << "\n\t remaining_payload=" << state->remaining_payload(); - state->listener()->OnSettingsEnd(); - return DecodeStatus::kDecodeDone; -} - -DecodeStatus SettingsPayloadDecoder::HandleNotDone(FrameDecoderState* state, - DecodeBuffer* db, - DecodeStatus status) { - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called. - QUICHE_DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - return status; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.h deleted file mode 100644 index 7462888b540..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_ - -// Decodes the payload of a SETTINGS frame; for the RFC, see: -// http://httpwg.org/specs/rfc7540.html#SETTINGS - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class SettingsPayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE SettingsPayloadDecoder { - public: - // Starts the decoding of a SETTINGS frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a SETTINGS frame that has been split across decode - // buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::SettingsPayloadDecoderPeer; - - // Decodes as many settings as are available in the decode buffer, starting at - // the first byte of one setting; if a single setting is split across buffers, - // ResumeDecodingPayload will handle starting from where the previous call - // left off, and then will call StartDecodingSettings. - DecodeStatus StartDecodingSettings(FrameDecoderState* state, - DecodeBuffer* db); - - // Decoding a single SETTING returned a status other than kDecodeDone; this - // method just brings together the QUICHE_DCHECKs to reduce duplication. - DecodeStatus HandleNotDone(FrameDecoderState* state, - DecodeBuffer* db, - DecodeStatus status); - - Http2SettingFields setting_fields_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder_test.cc deleted file mode 100644 index 0261ed32050..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder_test.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/settings_payload_decoder.h" - -#include <stddef.h> - -#include <vector> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_constants_test_util.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class SettingsPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::SETTINGS; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::ACK; - } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnSettingsStart(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnSettingsStart: " << header; - EXPECT_EQ(Http2FrameType::SETTINGS, header.type) << header; - EXPECT_EQ(Http2FrameFlag(), header.flags) << header; - StartFrame(header)->OnSettingsStart(header); - } - - void OnSetting(const Http2SettingFields& setting_fields) override { - HTTP2_VLOG(1) << "Http2SettingFields: setting_fields=" << setting_fields; - CurrentFrame()->OnSetting(setting_fields); - } - - void OnSettingsEnd() override { - HTTP2_VLOG(1) << "OnSettingsEnd"; - EndFrame()->OnSettingsEnd(); - } - - void OnSettingsAck(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnSettingsAck: " << header; - StartAndEndFrame(header)->OnSettingsAck(header); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class SettingsPayloadDecoderTest - : public AbstractPayloadDecoderTest<SettingsPayloadDecoder, - SettingsPayloadDecoderPeer, - Listener> { - protected: - Http2SettingFields RandSettingsFields() { - Http2SettingFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the SETTINGS payload is not the correct size -// to hold exactly zero or more whole Http2SettingFields. -TEST_F(SettingsPayloadDecoderTest, SettingsWrongSize) { - auto approve_size = [](size_t size) { - // Should get an error if size is not an integral multiple of the size - // of one setting. - return 0 != (size % Http2SettingFields::EncodedSize()); - }; - Http2FrameBuilder fb; - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -// Confirm we get an error if the SETTINGS ACK payload is not empty. -TEST_F(SettingsPayloadDecoderTest, SettingsAkcWrongSize) { - auto approve_size = [](size_t size) { return size != 0; }; - Http2FrameBuilder fb; - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(Http2FrameFlag::ACK, fb.buffer(), - approve_size)); -} - -// SETTINGS must have stream_id==0, but the payload decoder doesn't check that. -TEST_F(SettingsPayloadDecoderTest, SettingsAck) { - for (int stream_id = 0; stream_id < 3; ++stream_id) { - Http2FrameHeader header(0, Http2FrameType::SETTINGS, - RandFlags() | Http2FrameFlag::ACK, stream_id); - set_frame_header(header); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays("", expected)); - } -} - -// Try several values of each known SETTINGS parameter. -TEST_F(SettingsPayloadDecoderTest, OneRealSetting) { - std::vector<uint32_t> values = {0, 1, 0xffffffff, Random().Rand32()}; - for (auto param : AllHttp2SettingsParameters()) { - for (uint32_t value : values) { - Http2SettingFields fields(param, value); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::SETTINGS, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.AppendSetting(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } - } -} - -// Decode a SETTINGS frame with lots of fields. -TEST_F(SettingsPayloadDecoderTest, ManySettings) { - const size_t num_settings = 100; - const size_t size = Http2SettingFields::EncodedSize() * num_settings; - Http2FrameHeader header(size, Http2FrameType::SETTINGS, - RandFlags(), // & ~Http2FrameFlag::ACK, - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - Http2FrameBuilder fb; - for (size_t n = 0; n < num_settings; ++n) { - Http2SettingFields fields(static_cast<Http2SettingsParameter>(n), - Random().Rand32()); - fb.Append(fields); - expected.AppendSetting(fields); - } - ASSERT_EQ(size, fb.size()); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.cc deleted file mode 100644 index a71ea785aba..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/unknown_payload_decoder.h" - -#include <stddef.h> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -DecodeStatus UnknownPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - - HTTP2_DVLOG(2) << "UnknownPayloadDecoder::StartDecodingPayload: " - << frame_header; - QUICHE_DCHECK(!IsSupportedHttp2FrameType(frame_header.type)) << frame_header; - QUICHE_DCHECK_LE(db->Remaining(), frame_header.payload_length); - - state->InitializeRemainders(); - state->listener()->OnUnknownStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus UnknownPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "UnknownPayloadDecoder::ResumeDecodingPayload " - << "remaining_payload=" << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - QUICHE_DCHECK(!IsSupportedHttp2FrameType(state->frame_header().type)) - << state->frame_header(); - QUICHE_DCHECK_LE(state->remaining_payload(), - state->frame_header().payload_length); - QUICHE_DCHECK_LE(db->Remaining(), state->remaining_payload()); - - size_t avail = db->Remaining(); - if (avail > 0) { - state->listener()->OnUnknownPayload(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() == 0) { - state->listener()->OnUnknownEnd(); - return DecodeStatus::kDecodeDone; - } - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.h deleted file mode 100644 index 7f89340077c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_ - -// Decodes the payload of a frame whose type unknown. According to the HTTP/2 -// specification (http://httpwg.org/specs/rfc7540.html#FrameHeader): -// Implementations MUST ignore and discard any frame that has -// a type that is unknown. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE UnknownPayloadDecoder { - public: - // Starts decoding a payload of unknown type; just passes it to the listener. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a payload of unknown type that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc deleted file mode 100644 index 722d109a118..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/unknown_payload_decoder.h" - -#include <stddef.h> - -#include <string> -#include <type_traits> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -namespace { -Http2FrameType g_unknown_frame_type; -} // namespace - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class UnknownPayloadDecoderPeer { - public: - static Http2FrameType FrameType() { return g_unknown_frame_type; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnUnknownStart(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnUnknownStart: " << header; - StartFrame(header)->OnUnknownStart(header); - } - - void OnUnknownPayload(const char* data, size_t len) override { - HTTP2_VLOG(1) << "OnUnknownPayload: len=" << len; - CurrentFrame()->OnUnknownPayload(data, len); - } - - void OnUnknownEnd() override { - HTTP2_VLOG(1) << "OnUnknownEnd"; - EndFrame()->OnUnknownEnd(); - } -}; - -constexpr bool SupportedFrameType = false; - -class UnknownPayloadDecoderTest - : public AbstractPayloadDecoderTest<UnknownPayloadDecoder, - UnknownPayloadDecoderPeer, - Listener, - SupportedFrameType>, - public ::testing::WithParamInterface<uint32_t> { - protected: - UnknownPayloadDecoderTest() : length_(GetParam()) { - HTTP2_VLOG(1) << "################ length_=" << length_ - << " ################"; - - // Each test case will choose a random frame type that isn't supported. - do { - g_unknown_frame_type = static_cast<Http2FrameType>(Random().Rand8()); - } while (IsSupportedHttp2FrameType(g_unknown_frame_type)); - } - - const uint32_t length_; -}; - -INSTANTIATE_TEST_SUITE_P(VariousLengths, - UnknownPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 255, 256)); - -TEST_P(UnknownPayloadDecoderTest, ValidLength) { - std::string unknown_payload = Random().RandString(length_); - Http2FrameHeader frame_header(length_, g_unknown_frame_type, Random().Rand8(), - RandStreamId()); - set_frame_header(frame_header); - FrameParts expected(frame_header, unknown_payload); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(unknown_payload, expected)); - // TODO(jamessynge): Check here (and in other such tests) that the fast - // and slow decode counts are both non-zero. Perhaps also add some kind of - // test for the listener having been called. That could simply be a test - // that there is a single collected FrameParts instance, and that it matches - // expected. -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.cc deleted file mode 100644 index d088e51fa49..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/window_update_payload_decoder.h" - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_http2_structures.h" -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -DecodeStatus WindowUpdatePayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - HTTP2_DVLOG(2) << "WindowUpdatePayloadDecoder::StartDecodingPayload: " - << frame_header; - - QUICHE_DCHECK_EQ(Http2FrameType::WINDOW_UPDATE, frame_header.type); - QUICHE_DCHECK_LE(db->Remaining(), total_length); - - // WINDOW_UPDATE frames have no flags. - QUICHE_DCHECK_EQ(0, frame_header.flags); - - // Special case for when the payload is the correct size and entirely in - // the buffer. - if (db->Remaining() == Http2WindowUpdateFields::EncodedSize() && - total_length == Http2WindowUpdateFields::EncodedSize()) { - DoDecode(&window_update_fields_, db); - state->listener()->OnWindowUpdate( - frame_header, window_update_fields_.window_size_increment); - return DecodeStatus::kDecodeDone; - } - state->InitializeRemainders(); - return HandleStatus(state, state->StartDecodingStructureInPayload( - &window_update_fields_, db)); -} - -DecodeStatus WindowUpdatePayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - HTTP2_DVLOG(2) << "ResumeDecodingPayload: remaining_payload=" - << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - QUICHE_DCHECK_EQ(Http2FrameType::WINDOW_UPDATE, state->frame_header().type); - QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus(state, state->ResumeDecodingStructureInPayload( - &window_update_fields_, db)); -} - -DecodeStatus WindowUpdatePayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - HTTP2_DVLOG(2) << "HandleStatus: status=" << status - << "; remaining_payload=" << state->remaining_payload(); - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - state->listener()->OnWindowUpdate( - state->frame_header(), window_update_fields_.window_size_increment); - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called. - QUICHE_DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.h deleted file mode 100644 index 3e6db43e823..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_ -#define QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_ - -// Decodes the payload of a WINDOW_UPDATE frame. - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/decoder/frame_decoder_state.h" -#include "http2/http2_structures.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class WindowUpdatePayloadDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE WindowUpdatePayloadDecoder { - public: - // Starts decoding a WINDOW_UPDATE frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a WINDOW_UPDATE frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::WindowUpdatePayloadDecoderPeer; - - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2WindowUpdateFields window_update_fields_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc deleted file mode 100644 index 4e69e9ba1cd..00000000000 --- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "http2/decoder/payload_decoders/window_update_payload_decoder.h" - -#include <stddef.h> - -#include "http2/decoder/http2_frame_decoder_listener.h" -#include "http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "http2/http2_constants.h" -#include "http2/http2_structures_test_util.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/test_tools/frame_parts.h" -#include "http2/test_tools/frame_parts_collector.h" -#include "http2/test_tools/http2_random.h" -#include "http2/tools/http2_frame_builder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class WindowUpdatePayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::WINDOW_UPDATE; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t window_size_increment) override { - HTTP2_VLOG(1) << "OnWindowUpdate: " << header - << "; window_size_increment=" << window_size_increment; - EXPECT_EQ(Http2FrameType::WINDOW_UPDATE, header.type); - StartAndEndFrame(header)->OnWindowUpdate(header, window_size_increment); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - HTTP2_VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class WindowUpdatePayloadDecoderTest - : public AbstractPayloadDecoderTest<WindowUpdatePayloadDecoder, - WindowUpdatePayloadDecoderPeer, - Listener> { - protected: - Http2WindowUpdateFields RandWindowUpdateFields() { - Http2WindowUpdateFields fields; - test::Randomize(&fields, RandomPtr()); - HTTP2_VLOG(3) << "RandWindowUpdateFields: " << fields; - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2WindowUpdateFields. -TEST_F(WindowUpdatePayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2WindowUpdateFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandWindowUpdateFields()); - fb.Append(RandWindowUpdateFields()); - fb.Append(RandWindowUpdateFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(WindowUpdatePayloadDecoderTest, VariousPayloads) { - for (int n = 0; n < 100; ++n) { - uint32_t stream_id = n == 0 ? 0 : RandStreamId(); - Http2WindowUpdateFields fields = RandWindowUpdateFields(); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::WINDOW_UPDATE, - RandFlags(), stream_id); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptWindowUpdateIncrement(fields.window_size_increment); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2 |