diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/http2/hpack')
68 files changed, 0 insertions, 11293 deletions
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.cc deleted file mode 100644 index 677f55ac063..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.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/hpack/decoder/hpack_block_collector.h" - -#include <algorithm> -#include <memory> - -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { - -HpackBlockCollector::HpackBlockCollector() = default; -HpackBlockCollector::HpackBlockCollector(const HpackBlockCollector& other) - : pending_entry_(other.pending_entry_), entries_(other.entries_) {} -HpackBlockCollector::~HpackBlockCollector() = default; - -void HpackBlockCollector::OnIndexedHeader(size_t index) { - pending_entry_.OnIndexedHeader(index); - PushPendingEntry(); -} -void HpackBlockCollector::OnDynamicTableSizeUpdate(size_t size) { - pending_entry_.OnDynamicTableSizeUpdate(size); - PushPendingEntry(); -} -void HpackBlockCollector::OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) { - pending_entry_.OnStartLiteralHeader(header_type, maybe_name_index); -} -void HpackBlockCollector::OnNameStart(bool huffman_encoded, size_t len) { - pending_entry_.OnNameStart(huffman_encoded, len); -} -void HpackBlockCollector::OnNameData(const char* data, size_t len) { - pending_entry_.OnNameData(data, len); -} -void HpackBlockCollector::OnNameEnd() { - pending_entry_.OnNameEnd(); -} -void HpackBlockCollector::OnValueStart(bool huffman_encoded, size_t len) { - pending_entry_.OnValueStart(huffman_encoded, len); -} -void HpackBlockCollector::OnValueData(const char* data, size_t len) { - pending_entry_.OnValueData(data, len); -} -void HpackBlockCollector::OnValueEnd() { - pending_entry_.OnValueEnd(); - PushPendingEntry(); -} - -void HpackBlockCollector::PushPendingEntry() { - EXPECT_TRUE(pending_entry_.IsComplete()); - HTTP2_DVLOG(2) << "PushPendingEntry: " << pending_entry_; - entries_.push_back(pending_entry_); - EXPECT_TRUE(entries_.back().IsComplete()); - pending_entry_.Clear(); -} -void HpackBlockCollector::Clear() { - pending_entry_.Clear(); - entries_.clear(); -} - -void HpackBlockCollector::ExpectIndexedHeader(size_t index) { - entries_.push_back( - HpackEntryCollector(HpackEntryType::kIndexedHeader, index)); -} -void HpackBlockCollector::ExpectDynamicTableSizeUpdate(size_t size) { - entries_.push_back( - HpackEntryCollector(HpackEntryType::kDynamicTableSizeUpdate, size)); -} -void HpackBlockCollector::ExpectNameIndexAndLiteralValue( - HpackEntryType type, - size_t index, - bool value_huffman, - const std::string& value) { - entries_.push_back(HpackEntryCollector(type, index, value_huffman, value)); -} -void HpackBlockCollector::ExpectLiteralNameAndValue(HpackEntryType type, - bool name_huffman, - const std::string& name, - bool value_huffman, - const std::string& value) { - entries_.push_back( - HpackEntryCollector(type, name_huffman, name, value_huffman, value)); -} - -void HpackBlockCollector::ShuffleEntries(Http2Random* rng) { - std::shuffle(entries_.begin(), entries_.end(), *rng); -} - -void HpackBlockCollector::AppendToHpackBlockBuilder( - HpackBlockBuilder* hbb) const { - QUICHE_CHECK(IsNotPending()); - for (const auto& entry : entries_) { - entry.AppendToHpackBlockBuilder(hbb); - } -} - -AssertionResult HpackBlockCollector::ValidateSoleIndexedHeader( - size_t ndx) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateIndexedHeader(ndx)); - return AssertionSuccess(); -} -AssertionResult HpackBlockCollector::ValidateSoleLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - absl::string_view expected_value) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateLiteralValueHeader( - expected_type, expected_index, expected_value_huffman, expected_value)); - return AssertionSuccess(); -} -AssertionResult HpackBlockCollector::ValidateSoleLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - absl::string_view expected_name, - bool expected_value_huffman, - absl::string_view expected_value) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateLiteralNameValueHeader( - expected_type, expected_name_huffman, expected_name, - expected_value_huffman, expected_value)); - return AssertionSuccess(); -} -AssertionResult HpackBlockCollector::ValidateSoleDynamicTableSizeUpdate( - size_t size) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateDynamicTableSizeUpdate(size)); - return AssertionSuccess(); -} - -AssertionResult HpackBlockCollector::VerifyEq( - const HpackBlockCollector& that) const { - VERIFY_EQ(pending_entry_, that.pending_entry_); - VERIFY_EQ(entries_, that.entries_); - return AssertionSuccess(); -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.h deleted file mode 100644 index 812c3dbcec1..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.h +++ /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. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ - -// HpackBlockCollector implements HpackEntryDecoderListener in order to record -// the calls using HpackEntryCollector instances (one per HPACK entry). This -// supports testing of HpackBlockDecoder, which decodes entire HPACK blocks. -// -// In addition to implementing the callback methods, HpackBlockCollector also -// supports comparing two HpackBlockCollector instances (i.e. an expected and -// an actual), or a sole HPACK entry against an expected value. - -#include <stddef.h> - -#include <string> -#include <vector> - -#include "absl/strings/string_view.h" -#include "http2/hpack/decoder/hpack_entry_collector.h" -#include "http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/hpack/tools/hpack_block_builder.h" -#include "http2/test_tools/http2_random.h" - -namespace http2 { -namespace test { - -class HpackBlockCollector : public HpackEntryDecoderListener { - public: - HpackBlockCollector(); - HpackBlockCollector(const HpackBlockCollector& other); - ~HpackBlockCollector() override; - - // Implementations of HpackEntryDecoderListener, forwarding to pending_entry_, - // an HpackEntryCollector for the "in-progress" HPACK entry. OnIndexedHeader - // and OnDynamicTableSizeUpdate are pending only for that one call, while - // OnStartLiteralHeader is followed by many calls, ending with OnValueEnd. - // Once all the calls for one HPACK entry have been received, PushPendingEntry - // is used to append the pending_entry_ entry to the collected entries_. - void OnIndexedHeader(size_t index) override; - void OnDynamicTableSizeUpdate(size_t size) override; - void OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - - // Methods for creating a set of expectations (i.e. HPACK entries to compare - // against those collected by another instance of HpackBlockCollector). - - // Add an HPACK entry for an indexed header. - void ExpectIndexedHeader(size_t index); - - // Add an HPACK entry for a dynamic table size update. - void ExpectDynamicTableSizeUpdate(size_t size); - - // Add an HPACK entry for a header entry with an index for the name, and a - // literal value. - void ExpectNameIndexAndLiteralValue(HpackEntryType type, - size_t index, - bool value_huffman, - const std::string& value); - - // Add an HPACK entry for a header entry with a literal name and value. - void ExpectLiteralNameAndValue(HpackEntryType type, - bool name_huffman, - const std::string& name, - bool value_huffman, - const std::string& value); - - // Shuffle the entries, in support of generating an HPACK block of entries - // in some random order. - void ShuffleEntries(Http2Random* rng); - - // Serialize entries_ to the HpackBlockBuilder. - void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const; - - // Return AssertionSuccess if there is just one entry, and it is an - // Indexed Header with the specified index. - ::testing::AssertionResult ValidateSoleIndexedHeader(size_t ndx) const; - - // Return AssertionSuccess if there is just one entry, and it is a - // Dynamic Table Size Update with the specified size. - ::testing::AssertionResult ValidateSoleDynamicTableSizeUpdate( - size_t size) const; - - // Return AssertionSuccess if there is just one entry, and it is a Header - // entry with an index for the name and a literal value. - ::testing::AssertionResult ValidateSoleLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - absl::string_view expected_value) const; - - // Return AssertionSuccess if there is just one entry, and it is a Header - // with a literal name and literal value. - ::testing::AssertionResult ValidateSoleLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - absl::string_view expected_name, - bool expected_value_huffman, - absl::string_view expected_value) const; - - bool IsNotPending() const { return pending_entry_.IsClear(); } - bool IsClear() const { return IsNotPending() && entries_.empty(); } - void Clear(); - - ::testing::AssertionResult VerifyEq(const HpackBlockCollector& that) const; - - private: - // Push the value of pending_entry_ onto entries_, and clear pending_entry_. - // The pending_entry_ must be complete. - void PushPendingEntry(); - - HpackEntryCollector pending_entry_; - std::vector<HpackEntryCollector> entries_; -}; - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc deleted file mode 100644 index 0a4c71cb754..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_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/hpack/decoder/hpack_block_decoder.h" - -#include <cstdint> - -#include "absl/strings/str_cat.h" -#include "http2/platform/api/http2_flag_utils.h" -#include "http2/platform/api/http2_flags.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -DecodeStatus HpackBlockDecoder::Decode(DecodeBuffer* db) { - if (!before_entry_) { - HTTP2_DVLOG(2) << "HpackBlockDecoder::Decode resume entry, db->Remaining=" - << db->Remaining(); - DecodeStatus status = entry_decoder_.Resume(db, listener_); - switch (status) { - case DecodeStatus::kDecodeDone: - before_entry_ = true; - break; - case DecodeStatus::kDecodeInProgress: - QUICHE_DCHECK_EQ(0u, db->Remaining()); - return DecodeStatus::kDecodeInProgress; - case DecodeStatus::kDecodeError: - HTTP2_CODE_COUNT_N(decompress_failure_3, 1, 23); - return DecodeStatus::kDecodeError; - } - } - QUICHE_DCHECK(before_entry_); - while (db->HasData()) { - HTTP2_DVLOG(2) << "HpackBlockDecoder::Decode start entry, db->Remaining=" - << db->Remaining(); - DecodeStatus status = entry_decoder_.Start(db, listener_); - switch (status) { - case DecodeStatus::kDecodeDone: - continue; - case DecodeStatus::kDecodeInProgress: - QUICHE_DCHECK_EQ(0u, db->Remaining()); - before_entry_ = false; - return DecodeStatus::kDecodeInProgress; - case DecodeStatus::kDecodeError: - HTTP2_CODE_COUNT_N(decompress_failure_3, 2, 23); - return DecodeStatus::kDecodeError; - } - QUICHE_DCHECK(false); - } - QUICHE_DCHECK(before_entry_); - return DecodeStatus::kDecodeDone; -} - -std::string HpackBlockDecoder::DebugString() const { - return absl::StrCat( - "HpackBlockDecoder(", entry_decoder_.DebugString(), ", listener@", - absl::Hex(reinterpret_cast<intptr_t>(listener_)), - (before_entry_ ? ", between entries)" : ", in an entry)")); -} - -std::ostream& operator<<(std::ostream& out, const HpackBlockDecoder& v) { - return out << v.DebugString(); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.h deleted file mode 100644 index 3d956b1656d..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.h +++ /dev/null @@ -1,69 +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_HPACK_DECODER_HPACK_BLOCK_DECODER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_ - -// HpackBlockDecoder decodes an entire HPACK block (or the available portion -// thereof in the DecodeBuffer) into entries, but doesn't include HPACK static -// or dynamic table support, so table indices remain indices at this level. -// Reports the entries to an HpackEntryDecoderListener. - -#include <string> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/hpack/decoder/hpack_decoding_error.h" -#include "http2/hpack/decoder/hpack_entry_decoder.h" -#include "http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE HpackBlockDecoder { - public: - explicit HpackBlockDecoder(HpackEntryDecoderListener* listener) - : listener_(listener) { - QUICHE_DCHECK_NE(listener_, nullptr); - } - ~HpackBlockDecoder() {} - - HpackBlockDecoder(const HpackBlockDecoder&) = delete; - HpackBlockDecoder& operator=(const HpackBlockDecoder&) = delete; - - // Prepares the decoder to start decoding a new HPACK block. Expected - // to be called from an implementation of Http2FrameDecoderListener's - // OnHeadersStart or OnPushPromiseStart methods. - void Reset() { - HTTP2_DVLOG(2) << "HpackBlockDecoder::Reset"; - before_entry_ = true; - } - - // Decode the fragment of the HPACK block contained in the decode buffer. - // Expected to be called from an implementation of Http2FrameDecoderListener's - // OnHpackFragment method. - DecodeStatus Decode(DecodeBuffer* db); - - // Is the decoding process between entries (i.e. would the next byte be the - // first byte of a new HPACK entry)? - bool before_entry() const { return before_entry_; } - - // Return error code after decoding error occurred in HpackEntryDecoder. - HpackDecodingError error() const { return entry_decoder_.error(); } - - std::string DebugString() const; - - private: - HpackEntryDecoder entry_decoder_; - HpackEntryDecoderListener* const listener_; - bool before_entry_ = true; -}; - -QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackBlockDecoder& v); - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder_test.cc deleted file mode 100644 index 216eba4d78c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder_test.cc +++ /dev/null @@ -1,293 +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/hpack/decoder/hpack_block_decoder.h" - -// Tests of HpackBlockDecoder. - -#include <cstdint> -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/hpack/decoder/hpack_block_collector.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/hpack/tools/hpack_block_builder.h" -#include "http2/hpack/tools/hpack_example.h" -#include "http2/platform/api/http2_test_helpers.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 { - -class HpackBlockDecoderTest : public RandomDecoderTest { - protected: - HpackBlockDecoderTest() : listener_(&collector_), decoder_(&listener_) { - stop_decode_on_done_ = false; - decoder_.Reset(); - // Make sure logging doesn't crash. Not examining the result. - std::ostringstream strm; - strm << decoder_; - } - - DecodeStatus StartDecoding(DecodeBuffer* db) override { - collector_.Clear(); - decoder_.Reset(); - return ResumeDecoding(db); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* db) override { - DecodeStatus status = decoder_.Decode(db); - - // Make sure logging doesn't crash. Not examining the result. - std::ostringstream strm; - strm << decoder_; - - return status; - } - - AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* db, - const Validator& validator) { - bool return_non_zero_on_first = false; - return RandomDecoderTest::DecodeAndValidateSeveralWays( - db, return_non_zero_on_first, validator); - } - - AssertionResult DecodeAndValidateSeveralWays(const HpackBlockBuilder& hbb, - const Validator& validator) { - DecodeBuffer db(hbb.buffer()); - return DecodeAndValidateSeveralWays(&db, validator); - } - - AssertionResult DecodeHpackExampleAndValidateSeveralWays( - absl::string_view hpack_example, - Validator validator) { - std::string input = HpackExampleToStringOrDie(hpack_example); - DecodeBuffer db(input); - return DecodeAndValidateSeveralWays(&db, validator); - } - - uint8_t Rand8() { return Random().Rand8(); } - - std::string Rand8String() { return Random().RandString(Rand8()); } - - HpackBlockCollector collector_; - HpackEntryDecoderVLoggingListener listener_; - HpackBlockDecoder decoder_; -}; - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.1 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_1) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( - HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, - "custom-header")); - }; - const char hpack_example[] = R"( - 40 | == Literal indexed == - 0a | Literal name (len = 10) - 6375 7374 6f6d 2d6b 6579 | custom-key - 0d | Literal value (len = 13) - 6375 7374 6f6d 2d68 6561 6465 72 | custom-header - | -> custom-key: - | custom-header - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.2 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_2) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader( - HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path")); - }; - const char hpack_example[] = R"( - 04 | == Literal not indexed == - | Indexed name (idx = 4) - | :path - 0c | Literal value (len = 12) - 2f73 616d 706c 652f 7061 7468 | /sample/path - | -> :path: /sample/path - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.3 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_3) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( - HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false, - "secret")); - }; - const char hpack_example[] = R"( - 10 | == Literal never indexed == - 08 | Literal name (len = 8) - 7061 7373 776f 7264 | password - 06 | Literal value (len = 6) - 7365 6372 6574 | secret - | -> password: secret - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.4 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_4) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2)); - }; - const char hpack_example[] = R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1 -TEST_F(HpackBlockDecoderTest, SpecExample_C_3_1) { - std::string example = R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - 41 | == Literal indexed == - | Indexed name (idx = 1) - | :authority - 0f | Literal value (len = 15) - 7777 772e 6578 616d 706c 652e 636f 6d | www.example.com - | -> :authority: - | www.example.com - )"; - HpackBlockCollector expected; - expected.ExpectIndexedHeader(2); - expected.ExpectIndexedHeader(6); - expected.ExpectIndexedHeader(4); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 1, false, "www.example.com"); - NoArgValidator do_check = [expected, this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); - }; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.5.1 -TEST_F(HpackBlockDecoderTest, SpecExample_C_5_1) { - std::string example = R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 32 | 302 - | -> :status: 302 - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 07 | Literal value (len = 7) - 7072 6976 6174 65 | private - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - 6e | == Literal indexed == - | Indexed name (idx = 46) - | location - 17 | Literal value (len = 23) - 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam - 706c 652e 636f 6d | ple.com - | -> location: - | https://www.example.com - )"; - HpackBlockCollector expected; - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 8, false, "302"); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 24, false, "private"); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 33, false, - "Mon, 21 Oct 2013 20:13:21 GMT"); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 46, false, "https://www.example.com"); - NoArgValidator do_check = [expected, this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); - }; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// Generate a bunch of HPACK block entries to expect, use those expectations -// to generate an HPACK block, then decode it and confirm it matches those -// expectations. Some of these are invalid (such as Indexed, with index=0), -// but well-formed, and the decoder doesn't check for validity, just -// well-formedness. That includes the validity of the strings not being checked, -// such as lower-case ascii for the names, and valid Huffman encodings. -TEST_F(HpackBlockDecoderTest, Computed) { - HpackBlockCollector expected; - expected.ExpectIndexedHeader(0); - expected.ExpectIndexedHeader(1); - expected.ExpectIndexedHeader(126); - expected.ExpectIndexedHeader(127); - expected.ExpectIndexedHeader(128); - expected.ExpectDynamicTableSizeUpdate(0); - expected.ExpectDynamicTableSizeUpdate(1); - expected.ExpectDynamicTableSizeUpdate(14); - expected.ExpectDynamicTableSizeUpdate(15); - expected.ExpectDynamicTableSizeUpdate(30); - expected.ExpectDynamicTableSizeUpdate(31); - expected.ExpectDynamicTableSizeUpdate(4095); - expected.ExpectDynamicTableSizeUpdate(4096); - expected.ExpectDynamicTableSizeUpdate(8192); - for (auto type : {HpackEntryType::kIndexedLiteralHeader, - HpackEntryType::kUnindexedLiteralHeader, - HpackEntryType::kNeverIndexedLiteralHeader}) { - for (bool value_huffman : {false, true}) { - // An entry with an index for the name. Ensure the name index - // is not zero by adding one to the Rand8() result. - expected.ExpectNameIndexAndLiteralValue(type, Rand8() + 1, value_huffman, - Rand8String()); - // And two entries with literal names, one plain, one huffman encoded. - expected.ExpectLiteralNameAndValue(type, false, Rand8String(), - value_huffman, Rand8String()); - expected.ExpectLiteralNameAndValue(type, true, Rand8String(), - value_huffman, Rand8String()); - } - } - // Shuffle the entries and serialize them to produce an HPACK block. - expected.ShuffleEntries(RandomPtr()); - HpackBlockBuilder hbb; - expected.AppendToHpackBlockBuilder(&hbb); - - NoArgValidator do_check = [expected, this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc deleted file mode 100644 index 37933f19630..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc +++ /dev/null @@ -1,125 +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/hpack/decoder/hpack_decoder.h" - -#include "http2/decoder/decode_status.h" -#include "http2/platform/api/http2_flag_utils.h" -#include "http2/platform/api/http2_flags.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -HpackDecoder::HpackDecoder(HpackDecoderListener* listener, - size_t max_string_size) - : decoder_state_(listener), - entry_buffer_(&decoder_state_, max_string_size), - block_decoder_(&entry_buffer_), - error_(HpackDecodingError::kOk) {} - -HpackDecoder::~HpackDecoder() = default; - -void HpackDecoder::set_max_string_size_bytes(size_t max_string_size_bytes) { - entry_buffer_.set_max_string_size_bytes(max_string_size_bytes); -} - -void HpackDecoder::ApplyHeaderTableSizeSetting(uint32_t max_header_table_size) { - decoder_state_.ApplyHeaderTableSizeSetting(max_header_table_size); -} - -bool HpackDecoder::StartDecodingBlock() { - HTTP2_DVLOG(3) << "HpackDecoder::StartDecodingBlock, error_detected=" - << (DetectError() ? "true" : "false"); - if (DetectError()) { - return false; - } - // TODO(jamessynge): Eliminate Reset(), which shouldn't be necessary - // if there are no errors, and shouldn't be necessary with errors if - // we never resume decoding after an error has been detected. - block_decoder_.Reset(); - decoder_state_.OnHeaderBlockStart(); - return true; -} - -bool HpackDecoder::DecodeFragment(DecodeBuffer* db) { - HTTP2_DVLOG(3) << "HpackDecoder::DecodeFragment, error_detected=" - << (DetectError() ? "true" : "false") - << ", size=" << db->Remaining(); - if (DetectError()) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 3, 23); - return false; - } - // Decode contents of db as an HPACK block fragment, forwards the decoded - // entries to entry_buffer_, which in turn forwards them to decode_state_, - // which finally forwards them to the HpackDecoderListener. - DecodeStatus status = block_decoder_.Decode(db); - if (status == DecodeStatus::kDecodeError) { - ReportError(block_decoder_.error(), ""); - HTTP2_CODE_COUNT_N(decompress_failure_3, 4, 23); - return false; - } else if (DetectError()) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 5, 23); - return false; - } - // Should be positioned between entries iff decoding is complete. - QUICHE_DCHECK_EQ(block_decoder_.before_entry(), - status == DecodeStatus::kDecodeDone) - << status; - if (!block_decoder_.before_entry()) { - entry_buffer_.BufferStringsIfUnbuffered(); - } - return true; -} - -bool HpackDecoder::EndDecodingBlock() { - HTTP2_DVLOG(3) << "HpackDecoder::EndDecodingBlock, error_detected=" - << (DetectError() ? "true" : "false"); - if (DetectError()) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 6, 23); - return false; - } - if (!block_decoder_.before_entry()) { - // The HPACK block ended in the middle of an entry. - ReportError(HpackDecodingError::kTruncatedBlock, ""); - HTTP2_CODE_COUNT_N(decompress_failure_3, 7, 23); - return false; - } - decoder_state_.OnHeaderBlockEnd(); - if (DetectError()) { - // HpackDecoderState will have reported the error. - HTTP2_CODE_COUNT_N(decompress_failure_3, 8, 23); - return false; - } - return true; -} - -bool HpackDecoder::DetectError() { - if (error_ != HpackDecodingError::kOk) { - return true; - } - - if (decoder_state_.error() != HpackDecodingError::kOk) { - HTTP2_DVLOG(2) << "Error detected in decoder_state_"; - HTTP2_CODE_COUNT_N(decompress_failure_3, 10, 23); - error_ = decoder_state_.error(); - detailed_error_ = decoder_state_.detailed_error(); - } - - return error_ != HpackDecodingError::kOk; -} - -void HpackDecoder::ReportError(HpackDecodingError error, - std::string detailed_error) { - HTTP2_DVLOG(3) << "HpackDecoder::ReportError is new=" - << (error_ == HpackDecodingError::kOk ? "true" : "false") - << ", error: " << HpackDecodingErrorToString(error); - if (error_ == HpackDecodingError::kOk) { - error_ = error; - detailed_error_ = detailed_error; - decoder_state_.listener()->OnHeaderErrorDetected( - HpackDecodingErrorToString(error)); - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h deleted file mode 100644 index 3ac581926a1..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h +++ /dev/null @@ -1,132 +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. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_H_ - -// Decodes HPACK blocks, calls an HpackDecoderListener with the decoded header -// entries. Also notifies the listener of errors and of the boundaries of the -// HPACK blocks. - -// TODO(jamessynge): Add feature allowing an HpackEntryDecoderListener -// sub-class (and possibly others) to be passed in for counting events, -// so that deciding whether to count is not done by having lots of if -// statements, but instead by inserting an indirection only when needed. - -// TODO(jamessynge): Consider whether to return false from methods below -// when an error has been previously detected. It protects calling code -// from its failure to pay attention to previous errors, but should we -// spend time to do that? - -#include <stddef.h> - -#include <cstdint> - -#include "http2/decoder/decode_buffer.h" -#include "http2/hpack/decoder/hpack_block_decoder.h" -#include "http2/hpack/decoder/hpack_decoder_listener.h" -#include "http2/hpack/decoder/hpack_decoder_state.h" -#include "http2/hpack/decoder/hpack_decoder_tables.h" -#include "http2/hpack/decoder/hpack_decoding_error.h" -#include "http2/hpack/decoder/hpack_whole_entry_buffer.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class HpackDecoderPeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE HpackDecoder { - public: - HpackDecoder(HpackDecoderListener* listener, size_t max_string_size); - virtual ~HpackDecoder(); - - HpackDecoder(const HpackDecoder&) = delete; - HpackDecoder& operator=(const HpackDecoder&) = delete; - - // max_string_size specifies the maximum size of an on-the-wire string (name - // or value, plain or Huffman encoded) that will be accepted. See sections - // 5.1 and 5.2 of RFC 7541. This is a defense against OOM attacks; HTTP/2 - // allows a decoder to enforce any limit of the size of the header lists - // that it is willing to decode, including less than the MAX_HEADER_LIST_SIZE - // setting, a setting that is initially unlimited. For example, we might - // choose to send a MAX_HEADER_LIST_SIZE of 64KB, and to use that same value - // as the upper bound for individual strings. - void set_max_string_size_bytes(size_t max_string_size_bytes); - - // ApplyHeaderTableSizeSetting notifies this object that this endpoint has - // received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from - // this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the - // maximum size of the dynamic table that this endpoint will use to decode - // HPACK blocks). - // Because a SETTINGS frame can contain SETTINGS_HEADER_TABLE_SIZE values, - // the caller must keep track of those multiple changes, and make - // corresponding calls to this method. In particular, a call must be made - // with the lowest value acknowledged by the peer, and a call must be made - // with the final value acknowledged, in that order; additional calls may - // be made if additional values were sent. These calls must be made between - // decoding the SETTINGS ACK, and before the next HPACK block is decoded. - void ApplyHeaderTableSizeSetting(uint32_t max_header_table_size); - - // Returns the most recently applied value of SETTINGS_HEADER_TABLE_SIZE. - size_t GetCurrentHeaderTableSizeSetting() const { - return decoder_state_.GetCurrentHeaderTableSizeSetting(); - } - - // Prepares the decoder for decoding a new HPACK block, and announces this to - // its listener. Returns true if OK to continue with decoding, false if an - // error has been detected, which for StartDecodingBlock means the error was - // detected while decoding a previous HPACK block. - bool StartDecodingBlock(); - - // Decodes a fragment (some or all of the remainder) of an HPACK block, - // reporting header entries (name & value pairs) that it completely decodes - // in the process to the listener. Returns true successfully decoded, false if - // an error has been detected, either during decoding of the fragment, or - // prior to this call. - bool DecodeFragment(DecodeBuffer* db); - - // Completes the process of decoding an HPACK block: if the HPACK block was - // properly terminated, announces the end of the header list to the listener - // and returns true; else returns false. - bool EndDecodingBlock(); - - // If no error has been detected so far, query |decoder_state_| for errors and - // set |error_| if necessary. Returns true if an error has ever been - // detected. - bool DetectError(); - - size_t GetDynamicTableSize() const { - return decoder_state_.GetDynamicTableSize(); - } - - // Error code if an error has occurred, HpackDecodingError::kOk otherwise. - HpackDecodingError error() const { return error_; } - - std::string detailed_error() const { return detailed_error_; } - - private: - friend class test::HpackDecoderPeer; - - // Reports an error to the listener IF this is the first error detected. - void ReportError(HpackDecodingError error, std::string detailed_error); - - // The decompressor state, as defined by HPACK (i.e. the static and dynamic - // tables). - HpackDecoderState decoder_state_; - - // Assembles the various parts of a header entry into whole entries. - HpackWholeEntryBuffer entry_buffer_; - - // The decoder of HPACK blocks into entry parts, passed to entry_buffer_. - HpackBlockDecoder block_decoder_; - - // Error code if an error has occurred, HpackDecodingError::kOk otherwise. - HpackDecodingError error_; - std::string detailed_error_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc deleted file mode 100644 index d1dea19330e..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc +++ /dev/null @@ -1,29 +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/hpack/decoder/hpack_decoder_listener.h" - -namespace http2 { - -HpackDecoderListener::HpackDecoderListener() = default; -HpackDecoderListener::~HpackDecoderListener() = default; - -HpackDecoderNoOpListener::HpackDecoderNoOpListener() = default; -HpackDecoderNoOpListener::~HpackDecoderNoOpListener() = default; - -void HpackDecoderNoOpListener::OnHeaderListStart() {} -void HpackDecoderNoOpListener::OnHeader(const std::string& /*name*/, - const std::string& /*value*/) {} -void HpackDecoderNoOpListener::OnHeaderListEnd() {} -void HpackDecoderNoOpListener::OnHeaderErrorDetected( - absl::string_view /*error_message*/) {} - -// static -HpackDecoderNoOpListener* HpackDecoderNoOpListener::NoOpListener() { - static HpackDecoderNoOpListener* static_instance = - new HpackDecoderNoOpListener(); - return static_instance; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h deleted file mode 100644 index d341025c82c..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h +++ /dev/null @@ -1,61 +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. - -// Defines HpackDecoderListener, the base class of listeners for HTTP header -// lists decoded from an HPACK block. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_ - -#include "absl/strings/string_view.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE HpackDecoderListener { - public: - HpackDecoderListener(); - virtual ~HpackDecoderListener(); - - // OnHeaderListStart is called at the start of decoding an HPACK block into - // an HTTP/2 header list. Will only be called once per block, even if it - // extends into CONTINUATION frames. - virtual void OnHeaderListStart() = 0; - - // Called for each header name-value pair that is decoded, in the order they - // appear in the HPACK block. Multiple values for a given key will be emitted - // as multiple calls to OnHeader. - virtual void OnHeader(const std::string& name, const std::string& value) = 0; - - // OnHeaderListEnd is called after successfully decoding an HPACK block into - // an HTTP/2 header list. Will only be called once per block, even if it - // extends into CONTINUATION frames. - virtual void OnHeaderListEnd() = 0; - - // OnHeaderErrorDetected is called if an error is detected while decoding. - // error_message may be used in a GOAWAY frame as the Opaque Data. - virtual void OnHeaderErrorDetected(absl::string_view error_message) = 0; -}; - -// A no-op implementation of HpackDecoderListener, useful for ignoring -// callbacks once an error is detected. -class QUICHE_EXPORT_PRIVATE HpackDecoderNoOpListener - : public HpackDecoderListener { - public: - HpackDecoderNoOpListener(); - ~HpackDecoderNoOpListener() override; - - void OnHeaderListStart() override; - void OnHeader(const std::string& name, const std::string& value) override; - void OnHeaderListEnd() override; - void OnHeaderErrorDetected(absl::string_view error_message) override; - - // Returns a listener that ignores all the calls. - static HpackDecoderNoOpListener* NoOpListener(); -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc deleted file mode 100644 index 92c7b25bb39..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc +++ /dev/null @@ -1,226 +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/hpack/decoder/hpack_decoder_state.h" - -#include <utility> - -#include "http2/http2_constants.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_logging.h" - -namespace http2 { -namespace { - -std::string ExtractString(HpackDecoderStringBuffer* string_buffer) { - if (string_buffer->IsBuffered()) { - return string_buffer->ReleaseString(); - } else { - auto result = std::string(string_buffer->str()); - string_buffer->Reset(); - return result; - } -} - -} // namespace - -HpackDecoderState::HpackDecoderState(HpackDecoderListener* listener) - : listener_(listener), - final_header_table_size_(Http2SettingsInfo::DefaultHeaderTableSize()), - lowest_header_table_size_(final_header_table_size_), - require_dynamic_table_size_update_(false), - allow_dynamic_table_size_update_(true), - saw_dynamic_table_size_update_(false), - error_(HpackDecodingError::kOk) { - QUICHE_CHECK(listener_); -} - -HpackDecoderState::~HpackDecoderState() = default; - -void HpackDecoderState::ApplyHeaderTableSizeSetting( - uint32_t header_table_size) { - HTTP2_DVLOG(2) << "HpackDecoderState::ApplyHeaderTableSizeSetting(" - << header_table_size << ")"; - QUICHE_DCHECK_LE(lowest_header_table_size_, final_header_table_size_); - if (header_table_size < lowest_header_table_size_) { - lowest_header_table_size_ = header_table_size; - } - final_header_table_size_ = header_table_size; - HTTP2_DVLOG(2) << "low water mark: " << lowest_header_table_size_; - HTTP2_DVLOG(2) << "final limit: " << final_header_table_size_; -} - -// Called to notify this object that we're starting to decode an HPACK block -// (e.g. a HEADERS or PUSH_PROMISE frame's header has been decoded). -void HpackDecoderState::OnHeaderBlockStart() { - HTTP2_DVLOG(2) << "HpackDecoderState::OnHeaderBlockStart"; - // This instance can't be reused after an error has been detected, as we must - // assume that the encoder and decoder compression states are no longer - // synchronized. - QUICHE_DCHECK(error_ == HpackDecodingError::kOk) - << HpackDecodingErrorToString(error_); - QUICHE_DCHECK_LE(lowest_header_table_size_, final_header_table_size_); - allow_dynamic_table_size_update_ = true; - saw_dynamic_table_size_update_ = false; - // If the peer has acknowledged a HEADER_TABLE_SIZE smaller than that which - // its HPACK encoder has been using, then the next HPACK block it sends MUST - // start with a Dynamic Table Size Update entry that is at least as low as - // lowest_header_table_size_. That may be followed by another as great as - // final_header_table_size_, if those are different. - require_dynamic_table_size_update_ = - (lowest_header_table_size_ < - decoder_tables_.current_header_table_size() || - final_header_table_size_ < decoder_tables_.header_table_size_limit()); - HTTP2_DVLOG(2) << "HpackDecoderState::OnHeaderListStart " - << "require_dynamic_table_size_update_=" - << require_dynamic_table_size_update_; - listener_->OnHeaderListStart(); -} - -void HpackDecoderState::OnIndexedHeader(size_t index) { - HTTP2_DVLOG(2) << "HpackDecoderState::OnIndexedHeader: " << index; - if (error_ != HpackDecodingError::kOk) { - return; - } - if (require_dynamic_table_size_update_) { - ReportError(HpackDecodingError::kMissingDynamicTableSizeUpdate, ""); - return; - } - allow_dynamic_table_size_update_ = false; - const HpackStringPair* entry = decoder_tables_.Lookup(index); - if (entry != nullptr) { - listener_->OnHeader(entry->name, entry->value); - } else { - ReportError(HpackDecodingError::kInvalidIndex, ""); - } -} - -void HpackDecoderState::OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) { - HTTP2_DVLOG(2) << "HpackDecoderState::OnNameIndexAndLiteralValue " - << entry_type << ", " << name_index << ", " - << value_buffer->str(); - if (error_ != HpackDecodingError::kOk) { - return; - } - if (require_dynamic_table_size_update_) { - ReportError(HpackDecodingError::kMissingDynamicTableSizeUpdate, ""); - return; - } - allow_dynamic_table_size_update_ = false; - const HpackStringPair* entry = decoder_tables_.Lookup(name_index); - if (entry != nullptr) { - std::string value(ExtractString(value_buffer)); - listener_->OnHeader(entry->name, value); - if (entry_type == HpackEntryType::kIndexedLiteralHeader) { - decoder_tables_.Insert(entry->name, std::move(value)); - } - } else { - ReportError(HpackDecodingError::kInvalidNameIndex, ""); - } -} - -void HpackDecoderState::OnLiteralNameAndValue( - HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) { - HTTP2_DVLOG(2) << "HpackDecoderState::OnLiteralNameAndValue " << entry_type - << ", " << name_buffer->str() << ", " << value_buffer->str(); - if (error_ != HpackDecodingError::kOk) { - return; - } - if (require_dynamic_table_size_update_) { - ReportError(HpackDecodingError::kMissingDynamicTableSizeUpdate, ""); - return; - } - allow_dynamic_table_size_update_ = false; - std::string name(ExtractString(name_buffer)); - std::string value(ExtractString(value_buffer)); - listener_->OnHeader(name, value); - if (entry_type == HpackEntryType::kIndexedLiteralHeader) { - decoder_tables_.Insert(std::move(name), std::move(value)); - } -} - -void HpackDecoderState::OnDynamicTableSizeUpdate(size_t size_limit) { - HTTP2_DVLOG(2) << "HpackDecoderState::OnDynamicTableSizeUpdate " << size_limit - << ", required=" - << (require_dynamic_table_size_update_ ? "true" : "false") - << ", allowed=" - << (allow_dynamic_table_size_update_ ? "true" : "false"); - if (error_ != HpackDecodingError::kOk) { - return; - } - QUICHE_DCHECK_LE(lowest_header_table_size_, final_header_table_size_); - if (!allow_dynamic_table_size_update_) { - // At most two dynamic table size updates allowed at the start, and not - // after a header. - ReportError(HpackDecodingError::kDynamicTableSizeUpdateNotAllowed, ""); - return; - } - if (require_dynamic_table_size_update_) { - // The new size must not be greater than the low water mark. - if (size_limit > lowest_header_table_size_) { - ReportError( - HpackDecodingError::kInitialDynamicTableSizeUpdateIsAboveLowWaterMark, - ""); - return; - } - require_dynamic_table_size_update_ = false; - } else if (size_limit > final_header_table_size_) { - // The new size must not be greater than the final max header table size - // that the peer acknowledged. - ReportError( - HpackDecodingError::kDynamicTableSizeUpdateIsAboveAcknowledgedSetting, - ""); - return; - } - decoder_tables_.DynamicTableSizeUpdate(size_limit); - if (saw_dynamic_table_size_update_) { - allow_dynamic_table_size_update_ = false; - } else { - saw_dynamic_table_size_update_ = true; - } - // We no longer need to keep an eye out for a lower header table size. - lowest_header_table_size_ = final_header_table_size_; -} - -void HpackDecoderState::OnHpackDecodeError(HpackDecodingError error, - std::string detailed_error) { - HTTP2_DVLOG(2) << "HpackDecoderState::OnHpackDecodeError " - << HpackDecodingErrorToString(error); - if (error_ == HpackDecodingError::kOk) { - ReportError(error, detailed_error); - } -} - -void HpackDecoderState::OnHeaderBlockEnd() { - HTTP2_DVLOG(2) << "HpackDecoderState::OnHeaderBlockEnd"; - if (error_ != HpackDecodingError::kOk) { - return; - } - if (require_dynamic_table_size_update_) { - // Apparently the HPACK block was empty, but we needed it to contain at - // least 1 dynamic table size update. - ReportError(HpackDecodingError::kMissingDynamicTableSizeUpdate, ""); - } else { - listener_->OnHeaderListEnd(); - } -} - -void HpackDecoderState::ReportError(HpackDecodingError error, - std::string detailed_error) { - HTTP2_DVLOG(2) << "HpackDecoderState::ReportError is new=" - << (error_ == HpackDecodingError::kOk ? "true" : "false") - << ", error: " << HpackDecodingErrorToString(error); - if (error_ == HpackDecodingError::kOk) { - listener_->OnHeaderErrorDetected(HpackDecodingErrorToString(error)); - error_ = error; - detailed_error_ = detailed_error; - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h deleted file mode 100644 index 3040c181471..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h +++ /dev/null @@ -1,138 +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. - -// HpackDecoderState maintains the HPACK decompressor state; i.e. updates the -// HPACK dynamic table according to RFC 7541 as the entries in an HPACK block -// are decoded, and reads from the static and dynamic tables in order to build -// complete header entries. Calls an HpackDecoderListener with the completely -// decoded headers (i.e. after resolving table indices into names or values), -// thus translating the decoded HPACK entries into HTTP/2 headers. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_ - -#include <stddef.h> - -#include <cstdint> - -#include "absl/strings/string_view.h" -#include "http2/hpack/decoder/hpack_decoder_listener.h" -#include "http2/hpack/decoder/hpack_decoder_string_buffer.h" -#include "http2/hpack/decoder/hpack_decoder_tables.h" -#include "http2/hpack/decoder/hpack_decoding_error.h" -#include "http2/hpack/decoder/hpack_whole_entry_listener.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { -class HpackDecoderStatePeer; -} // namespace test - -class QUICHE_EXPORT_PRIVATE HpackDecoderState : public HpackWholeEntryListener { - public: - explicit HpackDecoderState(HpackDecoderListener* listener); - ~HpackDecoderState() override; - - HpackDecoderState(const HpackDecoderState&) = delete; - HpackDecoderState& operator=(const HpackDecoderState&) = delete; - - // Set the listener to be notified when a whole entry has been decoded, - // including resolving name or name and value references. - // The listener may be changed at any time. - HpackDecoderListener* listener() const { return listener_; } - - // ApplyHeaderTableSizeSetting notifies this object that this endpoint has - // received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from - // this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the - // maximum size of the dynamic table that this endpoint will use to decode - // HPACK blocks). - // Because a SETTINGS frame can contain SETTINGS_HEADER_TABLE_SIZE values, - // the caller must keep track of those multiple changes, and make - // corresponding calls to this method. In particular, a call must be made - // with the lowest value acknowledged by the peer, and a call must be made - // with the final value acknowledged, in that order; additional calls may - // be made if additional values were sent. These calls must be made between - // decoding the SETTINGS ACK, and before the next HPACK block is decoded. - void ApplyHeaderTableSizeSetting(uint32_t max_header_table_size); - - // Returns the most recently applied value of SETTINGS_HEADER_TABLE_SIZE. - size_t GetCurrentHeaderTableSizeSetting() const { - return final_header_table_size_; - } - - // OnHeaderBlockStart notifies this object that we're starting to decode the - // HPACK payload of a HEADERS or PUSH_PROMISE frame. - void OnHeaderBlockStart(); - - // Implement the HpackWholeEntryListener methods, each of which notifies this - // object when an entire entry has been decoded. - void OnIndexedHeader(size_t index) override; - void OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) override; - void OnLiteralNameAndValue(HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) override; - void OnDynamicTableSizeUpdate(size_t size) override; - void OnHpackDecodeError(HpackDecodingError error, - std::string detailed_error) override; - - // OnHeaderBlockEnd notifies this object that an entire HPACK block has been - // decoded, which might have extended into CONTINUATION blocks. - void OnHeaderBlockEnd(); - - // Returns error code after an error has been detected and reported. - // No further callbacks will be made to the listener. - HpackDecodingError error() const { return error_; } - - size_t GetDynamicTableSize() const { - return decoder_tables_.current_header_table_size(); - } - - const HpackDecoderTables& decoder_tables_for_test() const { - return decoder_tables_; - } - - std::string detailed_error() const { return detailed_error_; } - - private: - friend class test::HpackDecoderStatePeer; - - // Reports an error to the listener IF this is the first error detected. - void ReportError(HpackDecodingError error, std::string detailed_error); - - // The static and dynamic HPACK tables. - HpackDecoderTables decoder_tables_; - - // The listener to be notified of headers, the start and end of header - // lists, and of errors. - HpackDecoderListener* listener_; - - // The most recent HEADER_TABLE_SIZE setting acknowledged by the peer. - uint32_t final_header_table_size_; - - // The lowest HEADER_TABLE_SIZE setting acknowledged by the peer; valid until - // the next HPACK block is decoded. - // TODO(jamessynge): Test raising the HEADER_TABLE_SIZE. - uint32_t lowest_header_table_size_; - - // Must the next (first) HPACK entry be a dynamic table size update? - bool require_dynamic_table_size_update_; - - // May the next (first or second) HPACK entry be a dynamic table size update? - bool allow_dynamic_table_size_update_; - - // Have we already seen a dynamic table size update in this HPACK block? - bool saw_dynamic_table_size_update_; - - // Has an error already been detected and reported to the listener? - HpackDecodingError error_; - std::string detailed_error_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc deleted file mode 100644 index 7e36a178a74..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc +++ /dev/null @@ -1,549 +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/hpack/decoder/hpack_decoder_state.h" - -// Tests of HpackDecoderState. - -#include <utility> -#include <vector> - -#include "absl/strings/string_view.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/http2_constants.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::Eq; -using ::testing::Mock; -using ::testing::StrictMock; - -namespace http2 { -namespace test { -class HpackDecoderStatePeer { - public: - static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) { - return &state->decoder_tables_; - } -}; - -namespace { - -class MockHpackDecoderListener : public HpackDecoderListener { - public: - MOCK_METHOD(void, OnHeaderListStart, (), (override)); - MOCK_METHOD(void, - OnHeader, - (const std::string& name, const std::string& value), - (override)); - MOCK_METHOD(void, OnHeaderListEnd, (), (override)); - MOCK_METHOD(void, - OnHeaderErrorDetected, - (absl::string_view error_message), - (override)); -}; - -enum StringBacking { STATIC, UNBUFFERED, BUFFERED }; - -class HpackDecoderStateTest : public QuicheTest { - protected: - HpackDecoderStateTest() : decoder_state_(&listener_) {} - - HpackDecoderTables* GetDecoderTables() { - return HpackDecoderStatePeer::GetDecoderTables(&decoder_state_); - } - - const HpackStringPair* Lookup(size_t index) { - return GetDecoderTables()->Lookup(index); - } - - size_t current_header_table_size() { - return GetDecoderTables()->current_header_table_size(); - } - - size_t header_table_size_limit() { - return GetDecoderTables()->header_table_size_limit(); - } - - void set_header_table_size_limit(size_t size) { - GetDecoderTables()->DynamicTableSizeUpdate(size); - } - - void SetStringBuffer(const char* s, - StringBacking backing, - HpackDecoderStringBuffer* string_buffer) { - switch (backing) { - case STATIC: - string_buffer->Set(s, true); - break; - case UNBUFFERED: - string_buffer->Set(s, false); - break; - case BUFFERED: - string_buffer->Set(s, false); - string_buffer->BufferStringIfUnbuffered(); - break; - } - } - - void SetName(const char* s, StringBacking backing) { - SetStringBuffer(s, backing, &name_buffer_); - } - - void SetValue(const char* s, StringBacking backing) { - SetStringBuffer(s, backing, &value_buffer_); - } - - void SendStartAndVerifyCallback() { - EXPECT_CALL(listener_, OnHeaderListStart()); - decoder_state_.OnHeaderBlockStart(); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendSizeUpdate(size_t size) { - decoder_state_.OnDynamicTableSizeUpdate(size); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendIndexAndVerifyCallback(size_t index, - HpackEntryType /*expected_type*/, - const char* expected_name, - const char* expected_value) { - EXPECT_CALL(listener_, OnHeader(Eq(expected_name), Eq(expected_value))); - decoder_state_.OnIndexedHeader(index); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendValueAndVerifyCallback(size_t name_index, - HpackEntryType entry_type, - const char* name, - const char* value, - StringBacking value_backing) { - SetValue(value, value_backing); - EXPECT_CALL(listener_, OnHeader(Eq(name), Eq(value))); - decoder_state_.OnNameIndexAndLiteralValue(entry_type, name_index, - &value_buffer_); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendNameAndValueAndVerifyCallback(HpackEntryType entry_type, - const char* name, - StringBacking name_backing, - const char* value, - StringBacking value_backing) { - SetName(name, name_backing); - SetValue(value, value_backing); - EXPECT_CALL(listener_, OnHeader(Eq(name), Eq(value))); - decoder_state_.OnLiteralNameAndValue(entry_type, &name_buffer_, - &value_buffer_); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendEndAndVerifyCallback() { - EXPECT_CALL(listener_, OnHeaderListEnd()); - decoder_state_.OnHeaderBlockEnd(); - Mock::VerifyAndClearExpectations(&listener_); - } - - // dynamic_index is one-based, because that is the way RFC 7541 shows it. - AssertionResult VerifyEntry(size_t dynamic_index, - const char* name, - const char* value) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_NE(entry, nullptr); - VERIFY_EQ(entry->name, name); - VERIFY_EQ(entry->value, value); - return AssertionSuccess(); - } - AssertionResult VerifyNoEntry(size_t dynamic_index) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_EQ(entry, nullptr); - return AssertionSuccess(); - } - AssertionResult VerifyDynamicTableContents( - const std::vector<std::pair<const char*, const char*>>& entries) { - size_t index = 1; - for (const auto& entry : entries) { - VERIFY_SUCCESS(VerifyEntry(index, entry.first, entry.second)); - ++index; - } - VERIFY_SUCCESS(VerifyNoEntry(index)); - return AssertionSuccess(); - } - - StrictMock<MockHpackDecoderListener> listener_; - HpackDecoderState decoder_state_; - HpackDecoderStringBuffer name_buffer_, value_buffer_; -}; - -// Test based on RFC 7541, section C.3: Request Examples without Huffman Coding. -// This section shows several consecutive header lists, corresponding to HTTP -// requests, on the same connection. -TEST_F(HpackDecoderStateTest, C3_RequestExamples) { - // C.3.1 First Request - // - // Header list to encode: - // - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method", - "GET"); - SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme", - "http"); - SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/"); - SendValueAndVerifyCallback(1, HpackEntryType::kIndexedLiteralHeader, - ":authority", "www.example.com", UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 57) :authority: www.example.com - // Table size: 57 - - ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}})); - ASSERT_EQ(57u, current_header_table_size()); - - // C.3.2 Second Request - // - // Header list to encode: - // - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com - // cache-control: no-cache - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method", - "GET"); - SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme", - "http"); - SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/"); - SendIndexAndVerifyCallback(62, HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"); - SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader, - "cache-control", "no-cache", UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 53) cache-control: no-cache - // [ 2] (s = 57) :authority: www.example.com - // Table size: 110 - - ASSERT_TRUE(VerifyDynamicTableContents( - {{"cache-control", "no-cache"}, {":authority", "www.example.com"}})); - ASSERT_EQ(110u, current_header_table_size()); - - // C.3.3 Third Request - // - // Header list to encode: - // - // :method: GET - // :scheme: https - // :path: /index.html - // :authority: www.example.com - // custom-key: custom-value - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method", - "GET"); - SendIndexAndVerifyCallback(7, HpackEntryType::kIndexedHeader, ":scheme", - "https"); - SendIndexAndVerifyCallback(5, HpackEntryType::kIndexedHeader, ":path", - "/index.html"); - SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"); - SendNameAndValueAndVerifyCallback(HpackEntryType::kIndexedLiteralHeader, - "custom-key", UNBUFFERED, "custom-value", - UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 54) custom-key: custom-value - // [ 2] (s = 53) cache-control: no-cache - // [ 3] (s = 57) :authority: www.example.com - // Table size: 164 - - ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"}, - {"cache-control", "no-cache"}, - {":authority", "www.example.com"}})); - ASSERT_EQ(164u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.5: Response Examples without Huffman -// Coding. This section shows several consecutive header lists, corresponding -// to HTTP responses, on the same connection. The HTTP/2 setting parameter -// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing -// some evictions to occur. -TEST_F(HpackDecoderStateTest, C5_ResponseExamples) { - set_header_table_size_limit(256); - - // C.5.1 First Response - // - // Header list to encode: - // - // :status: 302 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - SendStartAndVerifyCallback(); - SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader, - ":status", "302", BUFFERED); - SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader, - "cache-control", "private", UNBUFFERED); - SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date", - "Mon, 21 Oct 2013 20:13:21 GMT", UNBUFFERED); - SendValueAndVerifyCallback(46, HpackEntryType::kIndexedLiteralHeader, - "location", "https://www.example.com", UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 63) location: https://www.example.com - // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 3] (s = 52) cache-control: private - // [ 4] (s = 42) :status: 302 - // Table size: 222 - - ASSERT_TRUE( - VerifyDynamicTableContents({{"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}, - {":status", "302"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.2 Second Response - // - // The (":status", "302") header field is evicted from the dynamic table to - // free space to allow adding the (":status", "307") header field. - // - // Header list to encode: - // - // :status: 307 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - SendStartAndVerifyCallback(); - SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader, - ":status", "307", BUFFERED); - SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader, - "cache-control", "private"); - SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "date", - "Mon, 21 Oct 2013 20:13:21 GMT"); - SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 42) :status: 307 - // [ 2] (s = 63) location: https://www.example.com - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 4] (s = 52) cache-control: private - // Table size: 222 - - ASSERT_TRUE( - VerifyDynamicTableContents({{":status", "307"}, - {"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.3 Third Response - // - // Several header fields are evicted from the dynamic table during the - // processing of this header list. - // - // Header list to encode: - // - // :status: 200 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:22 GMT - // location: https://www.example.com - // content-encoding: gzip - // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1 - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(8, HpackEntryType::kIndexedHeader, ":status", - "200"); - SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader, - "cache-control", "private"); - SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date", - "Mon, 21 Oct 2013 20:13:22 GMT", BUFFERED); - SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"); - SendValueAndVerifyCallback(26, HpackEntryType::kIndexedLiteralHeader, - "content-encoding", "gzip", UNBUFFERED); - SendValueAndVerifyCallback( - 55, HpackEntryType::kIndexedLiteralHeader, "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", BUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; - // max-age=3600; version=1 - // [ 2] (s = 52) content-encoding: gzip - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT - // Table size: 215 - - ASSERT_TRUE(VerifyDynamicTableContents( - {{"set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - {"content-encoding", "gzip"}, - {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}})); - ASSERT_EQ(215u, current_header_table_size()); -} - -// Confirm that the table size can be changed, but at most twice. -TEST_F(HpackDecoderStateTest, OptionalTableSizeChanges) { - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - SendSizeUpdate(1024); - EXPECT_EQ(1024u, header_table_size_limit()); - SendSizeUpdate(0); - EXPECT_EQ(0u, header_table_size_limit()); - - // Three updates aren't allowed. - EXPECT_CALL(listener_, OnHeaderErrorDetected( - Eq("Dynamic table size update not allowed"))); - SendSizeUpdate(0); -} - -// Confirm that required size updates are indeed required before headers. -TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeHeader) { - EXPECT_EQ(4096u, decoder_state_.GetCurrentHeaderTableSizeSetting()); - decoder_state_.ApplyHeaderTableSizeSetting(1024); - decoder_state_.ApplyHeaderTableSizeSetting(2048); - EXPECT_EQ(2048u, decoder_state_.GetCurrentHeaderTableSizeSetting()); - - // First provide the required update, and an allowed second update. - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - SendSizeUpdate(1024); - EXPECT_EQ(1024u, header_table_size_limit()); - SendSizeUpdate(1500); - EXPECT_EQ(1500u, header_table_size_limit()); - SendEndAndVerifyCallback(); - - // Another HPACK block, but this time missing the required size update. - decoder_state_.ApplyHeaderTableSizeSetting(1024); - EXPECT_EQ(1024u, decoder_state_.GetCurrentHeaderTableSizeSetting()); - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(Eq("Missing dynamic table size update"))); - decoder_state_.OnIndexedHeader(1); - - // Further decoded entries are ignored. - decoder_state_.OnIndexedHeader(1); - decoder_state_.OnDynamicTableSizeUpdate(1); - SetValue("value", UNBUFFERED); - decoder_state_.OnNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_); - SetName("name", UNBUFFERED); - decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, - &name_buffer_, &value_buffer_); - decoder_state_.OnHeaderBlockEnd(); - decoder_state_.OnHpackDecodeError(HpackDecodingError::kIndexVarintError, ""); -} - -// Confirm that required size updates are validated. -TEST_F(HpackDecoderStateTest, InvalidRequiredSizeUpdate) { - // Require a size update, but provide one that isn't small enough. - decoder_state_.ApplyHeaderTableSizeSetting(1024); - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - EXPECT_CALL( - listener_, - OnHeaderErrorDetected( - Eq("Initial dynamic table size update is above low water mark"))); - SendSizeUpdate(2048); -} - -// Confirm that required size updates are indeed required before the end. -TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeEnd) { - decoder_state_.ApplyHeaderTableSizeSetting(1024); - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(Eq("Missing dynamic table size update"))); - decoder_state_.OnHeaderBlockEnd(); -} - -// Confirm that optional size updates are validated. -TEST_F(HpackDecoderStateTest, InvalidOptionalSizeUpdate) { - // Require a size update, but provide one that isn't small enough. - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(Eq( - "Dynamic table size update is above acknowledged setting"))); - SendSizeUpdate(Http2SettingsInfo::DefaultHeaderTableSize() + 1); -} - -TEST_F(HpackDecoderStateTest, InvalidStaticIndex) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected( - Eq("Invalid index in indexed header field representation"))); - decoder_state_.OnIndexedHeader(0); -} - -TEST_F(HpackDecoderStateTest, InvalidDynamicIndex) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected( - Eq("Invalid index in indexed header field representation"))); - decoder_state_.OnIndexedHeader(kFirstDynamicTableIndex); -} - -TEST_F(HpackDecoderStateTest, InvalidNameIndex) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(Eq("Invalid index in literal header field " - "with indexed name representation"))); - SetValue("value", UNBUFFERED); - decoder_state_.OnNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, kFirstDynamicTableIndex, - &value_buffer_); -} - -TEST_F(HpackDecoderStateTest, ErrorsSuppressCallbacks) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(Eq("Name Huffman encoding error"))); - decoder_state_.OnHpackDecodeError(HpackDecodingError::kNameHuffmanError, ""); - - // Further decoded entries are ignored. - decoder_state_.OnIndexedHeader(1); - decoder_state_.OnDynamicTableSizeUpdate(1); - SetValue("value", UNBUFFERED); - decoder_state_.OnNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_); - SetName("name", UNBUFFERED); - decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, - &name_buffer_, &value_buffer_); - decoder_state_.OnHeaderBlockEnd(); - decoder_state_.OnHpackDecodeError(HpackDecodingError::kIndexVarintError, ""); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc deleted file mode 100644 index d03590377e3..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc +++ /dev/null @@ -1,239 +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/hpack/decoder/hpack_decoder_string_buffer.h" - -#include <utility> - -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - const HpackDecoderStringBuffer::State v) { - switch (v) { - case HpackDecoderStringBuffer::State::RESET: - return out << "RESET"; - case HpackDecoderStringBuffer::State::COLLECTING: - return out << "COLLECTING"; - case HpackDecoderStringBuffer::State::COMPLETE: - return out << "COMPLETE"; - } - // 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_50_1) - << "Invalid HpackDecoderStringBuffer::State: " << unknown; - return out << "HpackDecoderStringBuffer::State(" << unknown << ")"; -} - -std::ostream& operator<<(std::ostream& out, - const HpackDecoderStringBuffer::Backing v) { - switch (v) { - case HpackDecoderStringBuffer::Backing::RESET: - return out << "RESET"; - case HpackDecoderStringBuffer::Backing::UNBUFFERED: - return out << "UNBUFFERED"; - case HpackDecoderStringBuffer::Backing::BUFFERED: - return out << "BUFFERED"; - case HpackDecoderStringBuffer::Backing::STATIC: - return out << "STATIC"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - auto v2 = static_cast<int>(v); - HTTP2_BUG(http2_bug_50_2) - << "Invalid HpackDecoderStringBuffer::Backing: " << v2; - return out << "HpackDecoderStringBuffer::Backing(" << v2 << ")"; -} - -HpackDecoderStringBuffer::HpackDecoderStringBuffer() - : remaining_len_(0), - is_huffman_encoded_(false), - state_(State::RESET), - backing_(Backing::RESET) {} -HpackDecoderStringBuffer::~HpackDecoderStringBuffer() = default; - -void HpackDecoderStringBuffer::Reset() { - HTTP2_DVLOG(3) << "HpackDecoderStringBuffer::Reset"; - state_ = State::RESET; -} - -void HpackDecoderStringBuffer::Set(absl::string_view value, bool is_static) { - HTTP2_DVLOG(2) << "HpackDecoderStringBuffer::Set"; - QUICHE_DCHECK_EQ(state_, State::RESET); - value_ = value; - state_ = State::COMPLETE; - backing_ = is_static ? Backing::STATIC : Backing::UNBUFFERED; - // TODO(jamessynge): Determine which of these two fields must be set. - remaining_len_ = 0; - is_huffman_encoded_ = false; -} - -void HpackDecoderStringBuffer::OnStart(bool huffman_encoded, size_t len) { - HTTP2_DVLOG(2) << "HpackDecoderStringBuffer::OnStart"; - QUICHE_DCHECK_EQ(state_, State::RESET); - - remaining_len_ = len; - is_huffman_encoded_ = huffman_encoded; - state_ = State::COLLECTING; - - if (huffman_encoded) { - // We don't set, clear or use value_ for buffered strings until OnEnd. - decoder_.Reset(); - buffer_.clear(); - backing_ = Backing::BUFFERED; - - // Reserve space in buffer_ for the uncompressed string, assuming the - // maximum expansion. The shortest Huffman codes in the RFC are 5 bits long, - // which then expand to 8 bits during decoding (i.e. each code is for one - // plain text octet, aka byte), so the maximum size is 60% longer than the - // encoded size. - len = len * 8 / 5; - if (buffer_.capacity() < len) { - buffer_.reserve(len); - } - } else { - // Assume for now that we won't need to use buffer_, so don't reserve space - // in it. - backing_ = Backing::RESET; - // OnData is not called for empty (zero length) strings, so make sure that - // value_ is cleared. - value_ = absl::string_view(); - } -} - -bool HpackDecoderStringBuffer::OnData(const char* data, size_t len) { - HTTP2_DVLOG(2) << "HpackDecoderStringBuffer::OnData state=" << state_ - << ", backing=" << backing_; - QUICHE_DCHECK_EQ(state_, State::COLLECTING); - QUICHE_DCHECK_LE(len, remaining_len_); - remaining_len_ -= len; - - if (is_huffman_encoded_) { - QUICHE_DCHECK_EQ(backing_, Backing::BUFFERED); - return decoder_.Decode(absl::string_view(data, len), &buffer_); - } - - if (backing_ == Backing::RESET) { - // This is the first call to OnData. If data contains the entire string, - // don't copy the string. If we later find that the HPACK entry is split - // across input buffers, then we'll copy the string into buffer_. - if (remaining_len_ == 0) { - value_ = absl::string_view(data, len); - backing_ = Backing::UNBUFFERED; - return true; - } - - // We need to buffer the string because it is split across input buffers. - // Reserve space in buffer_ for the entire string. - backing_ = Backing::BUFFERED; - buffer_.reserve(remaining_len_ + len); - buffer_.assign(data, len); - return true; - } - - // This is not the first call to OnData for this string, so it should be - // buffered. - QUICHE_DCHECK_EQ(backing_, Backing::BUFFERED); - - // Append to the current contents of the buffer. - buffer_.append(data, len); - return true; -} - -bool HpackDecoderStringBuffer::OnEnd() { - HTTP2_DVLOG(2) << "HpackDecoderStringBuffer::OnEnd"; - QUICHE_DCHECK_EQ(state_, State::COLLECTING); - QUICHE_DCHECK_EQ(0u, remaining_len_); - - if (is_huffman_encoded_) { - QUICHE_DCHECK_EQ(backing_, Backing::BUFFERED); - // Did the Huffman encoding of the string end properly? - if (!decoder_.InputProperlyTerminated()) { - return false; // No, it didn't. - } - value_ = buffer_; - } else if (backing_ == Backing::BUFFERED) { - value_ = buffer_; - } - state_ = State::COMPLETE; - return true; -} - -void HpackDecoderStringBuffer::BufferStringIfUnbuffered() { - HTTP2_DVLOG(3) << "HpackDecoderStringBuffer::BufferStringIfUnbuffered state=" - << state_ << ", backing=" << backing_; - if (state_ != State::RESET && backing_ == Backing::UNBUFFERED) { - HTTP2_DVLOG(2) - << "HpackDecoderStringBuffer buffering std::string of length " - << value_.size(); - buffer_.assign(value_.data(), value_.size()); - if (state_ == State::COMPLETE) { - value_ = buffer_; - } - backing_ = Backing::BUFFERED; - } -} - -bool HpackDecoderStringBuffer::IsBuffered() const { - HTTP2_DVLOG(3) << "HpackDecoderStringBuffer::IsBuffered"; - return state_ != State::RESET && backing_ == Backing::BUFFERED; -} - -size_t HpackDecoderStringBuffer::BufferedLength() const { - HTTP2_DVLOG(3) << "HpackDecoderStringBuffer::BufferedLength"; - return IsBuffered() ? buffer_.size() : 0; -} - -absl::string_view HpackDecoderStringBuffer::str() const { - HTTP2_DVLOG(3) << "HpackDecoderStringBuffer::str"; - QUICHE_DCHECK_EQ(state_, State::COMPLETE); - return value_; -} - -absl::string_view HpackDecoderStringBuffer::GetStringIfComplete() const { - if (state_ != State::COMPLETE) { - return {}; - } - return str(); -} - -std::string HpackDecoderStringBuffer::ReleaseString() { - HTTP2_DVLOG(3) << "HpackDecoderStringBuffer::ReleaseString"; - QUICHE_DCHECK_EQ(state_, State::COMPLETE); - QUICHE_DCHECK_EQ(backing_, Backing::BUFFERED); - if (state_ == State::COMPLETE) { - state_ = State::RESET; - if (backing_ == Backing::BUFFERED) { - return std::move(buffer_); - } else { - return std::string(value_); - } - } - return ""; -} - -void HpackDecoderStringBuffer::OutputDebugStringTo(std::ostream& out) const { - out << "{state=" << state_; - if (state_ != State::RESET) { - out << ", backing=" << backing_; - out << ", remaining_len=" << remaining_len_; - out << ", is_huffman_encoded=" << is_huffman_encoded_; - if (backing_ == Backing::BUFFERED) { - out << ", buffer: " << buffer_; - } else { - out << ", value: " << value_; - } - } - out << "}"; -} - -std::ostream& operator<<(std::ostream& out, const HpackDecoderStringBuffer& v) { - v.OutputDebugStringTo(out); - return out; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h deleted file mode 100644 index 83f59eda593..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h +++ /dev/null @@ -1,102 +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_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_ - -// HpackDecoderStringBuffer helps an HPACK decoder to avoid copies of a string -// literal (name or value) except when necessary (e.g. when split across two -// or more HPACK block fragments). - -#include <stddef.h> - -#include <ostream> -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/hpack/huffman/hpack_huffman_decoder.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE HpackDecoderStringBuffer { - public: - enum class State : uint8_t { RESET, COLLECTING, COMPLETE }; - enum class Backing : uint8_t { RESET, UNBUFFERED, BUFFERED, STATIC }; - - HpackDecoderStringBuffer(); - ~HpackDecoderStringBuffer(); - - HpackDecoderStringBuffer(const HpackDecoderStringBuffer&) = delete; - HpackDecoderStringBuffer& operator=(const HpackDecoderStringBuffer&) = delete; - - void Reset(); - void Set(absl::string_view value, bool is_static); - - // Note that for Huffman encoded strings the length of the string after - // decoding may be larger (expected), the same or even smaller; the latter - // are unlikely, but possible if the encoder makes odd choices. - void OnStart(bool huffman_encoded, size_t len); - bool OnData(const char* data, size_t len); - bool OnEnd(); - void BufferStringIfUnbuffered(); - bool IsBuffered() const; - size_t BufferedLength() const; - - // Accessors for the completely collected string (i.e. Set or OnEnd has just - // been called, and no reset of the state has occurred). - - // Returns a string_view pointing to the backing store for the string, - // either the internal buffer or the original transport buffer (e.g. for a - // literal value that wasn't Huffman encoded, and that wasn't split across - // transport buffers). - absl::string_view str() const; - - // Same as str() if state_ is COMPLETE. Otherwise, returns empty string piece. - absl::string_view GetStringIfComplete() const; - - // Returns the completely collected string by value, using std::move in an - // effort to avoid unnecessary copies. ReleaseString() must not be called - // unless the string has been buffered (to avoid forcing a potentially - // unnecessary copy). ReleaseString() also resets the instance so that it can - // be used to collect another string. - std::string ReleaseString(); - - State state_for_testing() const { return state_; } - Backing backing_for_testing() const { return backing_; } - void OutputDebugStringTo(std::ostream& out) const; - - private: - // Storage for the string being buffered, if buffering is necessary - // (e.g. if Huffman encoded, buffer_ is storage for the decoded string). - std::string buffer_; - - // The string_view to be returned by HpackDecoderStringBuffer::str(). If - // a string has been collected, but not buffered, value_ points to that - // string. - absl::string_view value_; - - // The decoder to use if the string is Huffman encoded. - HpackHuffmanDecoder decoder_; - - // Count of bytes not yet passed to OnData. - size_t remaining_len_; - - // Is the HPACK string Huffman encoded? - bool is_huffman_encoded_; - - // State of the string decoding process. - State state_; - - // Where is the string stored? - Backing backing_; -}; - -QUICHE_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& out, - const HpackDecoderStringBuffer& v); - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc deleted file mode 100644 index 82244efe4eb..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc +++ /dev/null @@ -1,249 +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/hpack/decoder/hpack_decoder_string_buffer.h" - -// Tests of HpackDecoderStringBuffer. - -#include <initializer_list> - -#include "absl/strings/escaping.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::HasSubstr; - -namespace http2 { -namespace test { -namespace { - -class HpackDecoderStringBufferTest : public QuicheTest { - protected: - typedef HpackDecoderStringBuffer::State State; - typedef HpackDecoderStringBuffer::Backing Backing; - - State state() const { return buf_.state_for_testing(); } - Backing backing() const { return buf_.backing_for_testing(); } - - // We want to know that HTTP2_LOG(x) << buf_ will work in production should - // that be needed, so we test that it outputs the expected values. - AssertionResult VerifyLogHasSubstrs(std::initializer_list<std::string> strs) { - HTTP2_VLOG(1) << buf_; - std::ostringstream ss; - buf_.OutputDebugStringTo(ss); - std::string dbg_str(ss.str()); - for (const auto& expected : strs) { - VERIFY_THAT(dbg_str, HasSubstr(expected)); - } - return AssertionSuccess(); - } - - HpackDecoderStringBuffer buf_; -}; - -TEST_F(HpackDecoderStringBufferTest, SetStatic) { - absl::string_view data("static string"); - - EXPECT_EQ(state(), State::RESET); - EXPECT_TRUE(VerifyLogHasSubstrs({"state=RESET"})); - - buf_.Set(data, /*is_static*/ true); - HTTP2_LOG(INFO) << buf_; - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::STATIC); - EXPECT_EQ(data, buf_.str()); - EXPECT_EQ(data.data(), buf_.str().data()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=STATIC", "value: static string"})); - - // The string is static, so BufferStringIfUnbuffered won't change anything. - buf_.BufferStringIfUnbuffered(); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::STATIC); - EXPECT_EQ(data, buf_.str()); - EXPECT_EQ(data.data(), buf_.str().data()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=STATIC", "value: static string"})); -} - -TEST_F(HpackDecoderStringBufferTest, PlainWhole) { - absl::string_view data("some text."); - - HTTP2_LOG(INFO) << buf_; - EXPECT_EQ(state(), State::RESET); - - buf_.OnStart(/*huffman_encoded*/ false, data.size()); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::RESET); - HTTP2_LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(data.data(), data.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::UNBUFFERED); - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::UNBUFFERED); - EXPECT_EQ(0u, buf_.BufferedLength()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=UNBUFFERED", "value: some text."})); - - // We expect that the string buffer points to the passed in - // string_view's backing store. - EXPECT_EQ(data.data(), buf_.str().data()); - - // Now force it to buffer the string, after which it will still have the same - // string value, but the backing store will be different. - buf_.BufferStringIfUnbuffered(); - HTTP2_LOG(INFO) << buf_; - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - EXPECT_EQ(data, buf_.str()); - EXPECT_NE(data.data(), buf_.str().data()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=BUFFERED", "buffer: some text."})); -} - -TEST_F(HpackDecoderStringBufferTest, PlainSplit) { - absl::string_view data("some text."); - absl::string_view part1 = data.substr(0, 1); - absl::string_view part2 = data.substr(1); - - EXPECT_EQ(state(), State::RESET); - buf_.OnStart(/*huffman_encoded*/ false, data.size()); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::RESET); - - // OnData with only a part of the data, not the whole, so buf_ will buffer - // the data. - EXPECT_TRUE(buf_.OnData(part1.data(), part1.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), part1.size()); - HTTP2_LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(part2.data(), part2.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - HTTP2_LOG(INFO) << buf_; - - absl::string_view buffered = buf_.str(); - EXPECT_EQ(data, buffered); - EXPECT_NE(data.data(), buffered.data()); - - // The string is already buffered, so BufferStringIfUnbuffered should not make - // any change. - buf_.BufferStringIfUnbuffered(); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - EXPECT_EQ(buffered, buf_.str()); - EXPECT_EQ(buffered.data(), buf_.str().data()); -} - -TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) { - std::string encoded = absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff"); - absl::string_view decoded("www.example.com"); - - EXPECT_EQ(state(), State::RESET); - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - - EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), decoded.size()); - EXPECT_EQ(decoded, buf_.str()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"{state=COMPLETE", "backing=BUFFERED", "buffer: www.example.com}"})); - - std::string s = buf_.ReleaseString(); - EXPECT_EQ(s, decoded); - EXPECT_EQ(state(), State::RESET); -} - -TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) { - std::string encoded = absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff"); - std::string part1 = encoded.substr(0, 5); - std::string part2 = encoded.substr(5); - absl::string_view decoded("www.example.com"); - - EXPECT_EQ(state(), State::RESET); - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(0u, buf_.BufferedLength()); - HTTP2_LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(part1.data(), part1.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_GT(buf_.BufferedLength(), 0u); - EXPECT_LT(buf_.BufferedLength(), decoded.size()); - HTTP2_LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(part2.data(), part2.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), decoded.size()); - HTTP2_LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), decoded.size()); - EXPECT_EQ(decoded, buf_.str()); - HTTP2_LOG(INFO) << buf_; - - buf_.Reset(); - EXPECT_EQ(state(), State::RESET); - HTTP2_LOG(INFO) << buf_; -} - -TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) { - // Explicitly encode the End-of-String symbol, a no-no. - std::string encoded = absl::HexStringToBytes("ffffffff"); - - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - - EXPECT_FALSE(buf_.OnData(encoded.data(), encoded.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - - HTTP2_LOG(INFO) << buf_; -} - -TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) { - // Last byte of string doesn't end with prefix of End-of-String symbol. - std::string encoded = absl::HexStringToBytes("00"); - - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - - EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - - EXPECT_FALSE(buf_.OnEnd()); - HTTP2_LOG(INFO) << buf_; -} - -// TODO(jamessynge): Add tests for ReleaseString(). - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc deleted file mode 100644 index 9f50ec78490..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc +++ /dev/null @@ -1,148 +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/hpack/decoder/hpack_decoder_tables.h" - -#include "absl/strings/str_cat.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { -namespace { - -std::vector<HpackStringPair>* MakeStaticTable() { - auto* ptr = new std::vector<HpackStringPair>(); - ptr->reserve(kFirstDynamicTableIndex); - ptr->emplace_back("", ""); - -#define STATIC_TABLE_ENTRY(name, value, index) \ - QUICHE_DCHECK_EQ(ptr->size(), static_cast<size_t>(index)); \ - ptr->emplace_back(name, value) - -#include "http2/hpack/hpack_static_table_entries.inc" - -#undef STATIC_TABLE_ENTRY - - return ptr; -} - -const std::vector<HpackStringPair>* GetStaticTable() { - static const std::vector<HpackStringPair>* const g_static_table = - MakeStaticTable(); - return g_static_table; -} - -} // namespace - -HpackStringPair::HpackStringPair(std::string name, std::string value) - : name(std::move(name)), value(std::move(value)) { - HTTP2_DVLOG(3) << DebugString() << " ctor"; -} - -HpackStringPair::~HpackStringPair() { - HTTP2_DVLOG(3) << DebugString() << " dtor"; -} - -std::string HpackStringPair::DebugString() const { - return absl::StrCat("HpackStringPair(name=", name, ", value=", value, ")"); -} - -std::ostream& operator<<(std::ostream& os, const HpackStringPair& p) { - os << p.DebugString(); - return os; -} - -HpackDecoderStaticTable::HpackDecoderStaticTable( - const std::vector<HpackStringPair>* table) - : table_(table) {} - -HpackDecoderStaticTable::HpackDecoderStaticTable() : table_(GetStaticTable()) {} - -const HpackStringPair* HpackDecoderStaticTable::Lookup(size_t index) const { - if (0 < index && index < kFirstDynamicTableIndex) { - return &((*table_)[index]); - } - return nullptr; -} - -HpackDecoderDynamicTable::HpackDecoderDynamicTable() - : insert_count_(kFirstDynamicTableIndex - 1) {} -HpackDecoderDynamicTable::~HpackDecoderDynamicTable() = default; - -void HpackDecoderDynamicTable::DynamicTableSizeUpdate(size_t size_limit) { - HTTP2_DVLOG(3) << "HpackDecoderDynamicTable::DynamicTableSizeUpdate " - << size_limit; - EnsureSizeNoMoreThan(size_limit); - QUICHE_DCHECK_LE(current_size_, size_limit); - size_limit_ = size_limit; -} - -// TODO(jamessynge): Check somewhere before here that names received from the -// peer are valid (e.g. are lower-case, no whitespace, etc.). -void HpackDecoderDynamicTable::Insert(std::string name, std::string value) { - HpackStringPair entry(std::move(name), std::move(value)); - size_t entry_size = entry.size(); - HTTP2_DVLOG(2) << "InsertEntry of size=" << entry_size - << "\n name: " << entry.name - << "\n value: " << entry.value; - if (entry_size > size_limit_) { - HTTP2_DVLOG(2) << "InsertEntry: entry larger than table, removing " - << table_.size() << " entries, of total size " - << current_size_ << " bytes."; - table_.clear(); - current_size_ = 0; - return; - } - ++insert_count_; - size_t insert_limit = size_limit_ - entry_size; - EnsureSizeNoMoreThan(insert_limit); - table_.push_front(entry); - current_size_ += entry_size; - HTTP2_DVLOG(2) << "InsertEntry: current_size_=" << current_size_; - QUICHE_DCHECK_GE(current_size_, entry_size); - QUICHE_DCHECK_LE(current_size_, size_limit_); -} - -const HpackStringPair* HpackDecoderDynamicTable::Lookup(size_t index) const { - if (index < table_.size()) { - return &table_[index]; - } - return nullptr; -} - -void HpackDecoderDynamicTable::EnsureSizeNoMoreThan(size_t limit) { - HTTP2_DVLOG(2) << "EnsureSizeNoMoreThan limit=" << limit - << ", current_size_=" << current_size_; - // Not the most efficient choice, but any easy way to start. - while (current_size_ > limit) { - RemoveLastEntry(); - } - QUICHE_DCHECK_LE(current_size_, limit); -} - -void HpackDecoderDynamicTable::RemoveLastEntry() { - QUICHE_DCHECK(!table_.empty()); - if (!table_.empty()) { - HTTP2_DVLOG(2) << "RemoveLastEntry current_size_=" << current_size_ - << ", last entry size=" << table_.back().size(); - QUICHE_DCHECK_GE(current_size_, table_.back().size()); - current_size_ -= table_.back().size(); - table_.pop_back(); - // Empty IFF current_size_ == 0. - QUICHE_DCHECK_EQ(table_.empty(), current_size_ == 0); - } -} - -HpackDecoderTables::HpackDecoderTables() = default; -HpackDecoderTables::~HpackDecoderTables() = default; - -const HpackStringPair* HpackDecoderTables::Lookup(size_t index) const { - if (index < kFirstDynamicTableIndex) { - return static_table_.Lookup(index); - } else { - return dynamic_table_.Lookup(index - kFirstDynamicTableIndex); - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h deleted file mode 100644 index ef5b3d2d678..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h +++ /dev/null @@ -1,166 +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_HPACK_DECODER_HPACK_DECODER_TABLES_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_ - -// Static and dynamic tables for the HPACK decoder. See: -// http://httpwg.org/specs/rfc7541.html#indexing.tables - -// Note that the Lookup methods return nullptr if the requested index was not -// found. This should be treated as a COMPRESSION error according to the HTTP/2 -// spec, which is a connection level protocol error (i.e. the connection must -// be terminated). See these sections in the two RFCs: -// http://httpwg.org/specs/rfc7541.html#indexed.header.representation -// http://httpwg.org/specs/rfc7541.html#index.address.space -// http://httpwg.org/specs/rfc7540.html#HeaderBlock - -#include <stddef.h> - -#include <cstdint> -#include <iosfwd> -#include <string> -#include <utility> -#include <vector> - -#include "http2/http2_constants.h" -#include "common/platform/api/quiche_export.h" -#include "common/quiche_circular_deque.h" - -namespace http2 { -namespace test { -class HpackDecoderTablesPeer; -} // namespace test - -struct QUICHE_EXPORT_PRIVATE HpackStringPair { - HpackStringPair(std::string name, std::string value); - ~HpackStringPair(); - - // Returns the size of a header entry with this name and value, per the RFC: - // http://httpwg.org/specs/rfc7541.html#calculating.table.size - size_t size() const { return 32 + name.size() + value.size(); } - - std::string DebugString() const; - - const std::string name; - const std::string value; -}; - -QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, - const HpackStringPair& p); - -// See http://httpwg.org/specs/rfc7541.html#static.table.definition for the -// contents, and http://httpwg.org/specs/rfc7541.html#index.address.space for -// info about accessing the static table. -class QUICHE_EXPORT_PRIVATE HpackDecoderStaticTable { - public: - explicit HpackDecoderStaticTable(const std::vector<HpackStringPair>* table); - // Uses a global table shared by all threads. - HpackDecoderStaticTable(); - - // If index is valid, returns a pointer to the entry, otherwise returns - // nullptr. - const HpackStringPair* Lookup(size_t index) const; - - private: - friend class test::HpackDecoderTablesPeer; - const std::vector<HpackStringPair>* const table_; -}; - -// HpackDecoderDynamicTable implements HPACK compression feature "indexed -// headers"; previously sent headers may be referenced later by their index -// in the dynamic table. See these sections of the RFC: -// http://httpwg.org/specs/rfc7541.html#dynamic.table -// http://httpwg.org/specs/rfc7541.html#dynamic.table.management -class QUICHE_EXPORT_PRIVATE HpackDecoderDynamicTable { - public: - HpackDecoderDynamicTable(); - ~HpackDecoderDynamicTable(); - - HpackDecoderDynamicTable(const HpackDecoderDynamicTable&) = delete; - HpackDecoderDynamicTable& operator=(const HpackDecoderDynamicTable&) = delete; - - // Sets a new size limit, received from the peer; performs evictions if - // necessary to ensure that the current size does not exceed the new limit. - // The caller needs to have validated that size_limit does not - // exceed the acknowledged value of SETTINGS_HEADER_TABLE_SIZE. - void DynamicTableSizeUpdate(size_t size_limit); - - // Insert entry if possible. - // If entry is too large to insert, then dynamic table will be empty. - void Insert(std::string name, std::string value); - - // If index is valid, returns a pointer to the entry, otherwise returns - // nullptr. - const HpackStringPair* Lookup(size_t index) const; - - size_t size_limit() const { return size_limit_; } - size_t current_size() const { return current_size_; } - - private: - friend class test::HpackDecoderTablesPeer; - - // Drop older entries to ensure the size is not greater than limit. - void EnsureSizeNoMoreThan(size_t limit); - - // Removes the oldest dynamic table entry. - void RemoveLastEntry(); - - quiche::QuicheCircularDeque<HpackStringPair> table_; - - // The last received DynamicTableSizeUpdate value, initialized to - // SETTINGS_HEADER_TABLE_SIZE. - size_t size_limit_ = Http2SettingsInfo::DefaultHeaderTableSize(); - - size_t current_size_ = 0; - - // insert_count_ and debug_listener_ are used by a QUIC experiment; remove - // when the experiment is done. - size_t insert_count_; -}; - -class QUICHE_EXPORT_PRIVATE HpackDecoderTables { - public: - HpackDecoderTables(); - ~HpackDecoderTables(); - - HpackDecoderTables(const HpackDecoderTables&) = delete; - HpackDecoderTables& operator=(const HpackDecoderTables&) = delete; - - // Sets a new size limit, received from the peer; performs evictions if - // necessary to ensure that the current size does not exceed the new limit. - // The caller needs to have validated that size_limit does not - // exceed the acknowledged value of SETTINGS_HEADER_TABLE_SIZE. - void DynamicTableSizeUpdate(size_t size_limit) { - dynamic_table_.DynamicTableSizeUpdate(size_limit); - } - - // Insert entry if possible. - // If entry is too large to insert, then dynamic table will be empty. - void Insert(std::string name, std::string value) { - dynamic_table_.Insert(std::move(name), std::move(value)); - } - - // If index is valid, returns a pointer to the entry, otherwise returns - // nullptr. - const HpackStringPair* Lookup(size_t index) const; - - // The size limit that the peer (the HPACK encoder) has told the decoder it is - // currently operating with. Defaults to SETTINGS_HEADER_TABLE_SIZE, 4096. - size_t header_table_size_limit() const { return dynamic_table_.size_limit(); } - - // Sum of the sizes of the dynamic table entries. - size_t current_header_table_size() const { - return dynamic_table_.current_size(); - } - - private: - friend class test::HpackDecoderTablesPeer; - HpackDecoderStaticTable static_table_; - HpackDecoderDynamicTable dynamic_table_; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc deleted file mode 100644 index b7ed5273264..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc +++ /dev/null @@ -1,259 +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/hpack/decoder/hpack_decoder_tables.h" - -#include <algorithm> -#include <string> -#include <tuple> -#include <vector> - -#include "http2/hpack/http2_hpack_constants.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/random_util.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -class HpackDecoderTablesPeer { - public: - static size_t num_dynamic_entries(const HpackDecoderTables& tables) { - return tables.dynamic_table_.table_.size(); - } -}; - -namespace { -struct StaticEntry { - const char* name; - const char* value; - size_t index; -}; - -std::vector<StaticEntry> MakeSpecStaticEntries() { - std::vector<StaticEntry> static_entries; - -#define STATIC_TABLE_ENTRY(name, value, index) \ - QUICHE_DCHECK_EQ(static_entries.size() + 1, static_cast<size_t>(index)); \ - static_entries.push_back({name, value, index}); - -#include "http2/hpack/hpack_static_table_entries.inc" - -#undef STATIC_TABLE_ENTRY - - return static_entries; -} - -template <class C> -void ShuffleCollection(C* collection, Http2Random* r) { - std::shuffle(collection->begin(), collection->end(), *r); -} - -class HpackDecoderStaticTableTest : public QuicheTest { - protected: - HpackDecoderStaticTableTest() = default; - - std::vector<StaticEntry> shuffled_static_entries() { - std::vector<StaticEntry> entries = MakeSpecStaticEntries(); - ShuffleCollection(&entries, &random_); - return entries; - } - - // This test is in a function so that it can be applied to both the static - // table and the combined static+dynamic tables. - AssertionResult VerifyStaticTableContents() { - for (const auto& expected : shuffled_static_entries()) { - const HpackStringPair* found = Lookup(expected.index); - VERIFY_NE(found, nullptr); - VERIFY_EQ(expected.name, found->name) << expected.index; - VERIFY_EQ(expected.value, found->value) << expected.index; - } - - // There should be no entry with index 0. - VERIFY_EQ(nullptr, Lookup(0)); - return AssertionSuccess(); - } - - virtual const HpackStringPair* Lookup(size_t index) { - return static_table_.Lookup(index); - } - - Http2Random* RandomPtr() { return &random_; } - - Http2Random random_; - - private: - HpackDecoderStaticTable static_table_; -}; - -TEST_F(HpackDecoderStaticTableTest, StaticTableContents) { - EXPECT_TRUE(VerifyStaticTableContents()); -} - -size_t Size(const std::string& name, const std::string& value) { - return name.size() + value.size() + 32; -} - -// To support tests with more than a few of hand crafted changes to the dynamic -// table, we have another, exceedingly simple, implementation of the HPACK -// dynamic table containing FakeHpackEntry instances. We can thus compare the -// contents of the actual table with those in fake_dynamic_table_. - -typedef std::tuple<std::string, std::string, size_t> FakeHpackEntry; -const std::string& Name(const FakeHpackEntry& entry) { - return std::get<0>(entry); -} -const std::string& Value(const FakeHpackEntry& entry) { - return std::get<1>(entry); -} -size_t Size(const FakeHpackEntry& entry) { - return std::get<2>(entry); -} - -class HpackDecoderTablesTest : public HpackDecoderStaticTableTest { - protected: - const HpackStringPair* Lookup(size_t index) override { - return tables_.Lookup(index); - } - - size_t dynamic_size_limit() const { - return tables_.header_table_size_limit(); - } - size_t current_dynamic_size() const { - return tables_.current_header_table_size(); - } - size_t num_dynamic_entries() const { - return HpackDecoderTablesPeer::num_dynamic_entries(tables_); - } - - // Insert the name and value into fake_dynamic_table_. - void FakeInsert(const std::string& name, const std::string& value) { - FakeHpackEntry entry(name, value, Size(name, value)); - fake_dynamic_table_.insert(fake_dynamic_table_.begin(), entry); - } - - // Add up the size of all entries in fake_dynamic_table_. - size_t FakeSize() { - size_t sz = 0; - for (const auto& entry : fake_dynamic_table_) { - sz += Size(entry); - } - return sz; - } - - // If the total size of the fake_dynamic_table_ is greater than limit, - // keep the first N entries such that those N entries have a size not - // greater than limit, and such that keeping entry N+1 would have a size - // greater than limit. Returns the count of removed bytes. - size_t FakeTrim(size_t limit) { - size_t original_size = FakeSize(); - size_t total_size = 0; - for (size_t ndx = 0; ndx < fake_dynamic_table_.size(); ++ndx) { - total_size += Size(fake_dynamic_table_[ndx]); - if (total_size > limit) { - // Need to get rid of ndx and all following entries. - fake_dynamic_table_.erase(fake_dynamic_table_.begin() + ndx, - fake_dynamic_table_.end()); - return original_size - FakeSize(); - } - } - return 0; - } - - // Verify that the contents of the actual dynamic table match those in - // fake_dynamic_table_. - AssertionResult VerifyDynamicTableContents() { - VERIFY_EQ(current_dynamic_size(), FakeSize()); - VERIFY_EQ(num_dynamic_entries(), fake_dynamic_table_.size()); - - for (size_t ndx = 0; ndx < fake_dynamic_table_.size(); ++ndx) { - const HpackStringPair* found = Lookup(ndx + kFirstDynamicTableIndex); - VERIFY_NE(found, nullptr); - - const auto& expected = fake_dynamic_table_[ndx]; - VERIFY_EQ(Name(expected), found->name); - VERIFY_EQ(Value(expected), found->value); - } - - // Make sure there are no more entries. - VERIFY_EQ(nullptr, - Lookup(fake_dynamic_table_.size() + kFirstDynamicTableIndex)); - return AssertionSuccess(); - } - - // Apply an update to the limit on the maximum size of the dynamic table. - AssertionResult DynamicTableSizeUpdate(size_t size_limit) { - VERIFY_EQ(current_dynamic_size(), FakeSize()); - if (size_limit < current_dynamic_size()) { - // Will need to trim the dynamic table's oldest entries. - tables_.DynamicTableSizeUpdate(size_limit); - FakeTrim(size_limit); - return VerifyDynamicTableContents(); - } - // Shouldn't change the size. - tables_.DynamicTableSizeUpdate(size_limit); - return VerifyDynamicTableContents(); - } - - // Insert an entry into the dynamic table, confirming that trimming of entries - // occurs if the total size is greater than the limit, and that older entries - // move up by 1 index. - AssertionResult Insert(const std::string& name, const std::string& value) { - size_t old_count = num_dynamic_entries(); - tables_.Insert(name, value); - FakeInsert(name, value); - VERIFY_EQ(old_count + 1, fake_dynamic_table_.size()); - FakeTrim(dynamic_size_limit()); - VERIFY_EQ(current_dynamic_size(), FakeSize()); - VERIFY_EQ(num_dynamic_entries(), fake_dynamic_table_.size()); - return VerifyDynamicTableContents(); - } - - private: - HpackDecoderTables tables_; - - std::vector<FakeHpackEntry> fake_dynamic_table_; -}; - -TEST_F(HpackDecoderTablesTest, StaticTableContents) { - EXPECT_TRUE(VerifyStaticTableContents()); -} - -// Generate a bunch of random header entries, insert them, and confirm they -// present, as required by the RFC, using VerifyDynamicTableContents above on -// each Insert. Also apply various resizings of the dynamic table. -TEST_F(HpackDecoderTablesTest, RandomDynamicTable) { - EXPECT_EQ(0u, current_dynamic_size()); - EXPECT_TRUE(VerifyStaticTableContents()); - EXPECT_TRUE(VerifyDynamicTableContents()); - - std::vector<size_t> table_sizes; - table_sizes.push_back(dynamic_size_limit()); - table_sizes.push_back(0); - table_sizes.push_back(dynamic_size_limit() / 2); - table_sizes.push_back(dynamic_size_limit()); - table_sizes.push_back(dynamic_size_limit() / 2); - table_sizes.push_back(0); - table_sizes.push_back(dynamic_size_limit()); - - for (size_t limit : table_sizes) { - ASSERT_TRUE(DynamicTableSizeUpdate(limit)); - for (int insert_count = 0; insert_count < 100; ++insert_count) { - std::string name = - GenerateHttp2HeaderName(random_.UniformInRange(2, 40), RandomPtr()); - std::string value = - GenerateWebSafeString(random_.UniformInRange(2, 600), RandomPtr()); - ASSERT_TRUE(Insert(name, value)); - } - EXPECT_TRUE(VerifyStaticTableContents()); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc deleted file mode 100644 index c1439f9bc6b..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc +++ /dev/null @@ -1,1192 +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/hpack/decoder/hpack_decoder.h" - -// Tests of HpackDecoder. - -#include <string> -#include <tuple> -#include <utility> -#include <vector> - -#include "http2/decoder/decode_buffer.h" -#include "http2/hpack/decoder/hpack_decoder_listener.h" -#include "http2/hpack/decoder/hpack_decoder_state.h" -#include "http2/hpack/decoder/hpack_decoder_tables.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/hpack/tools/hpack_block_builder.h" -#include "http2/hpack/tools/hpack_example.h" -#include "http2/http2_constants.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/random_util.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::ElementsAreArray; -using ::testing::Eq; - -namespace http2 { -namespace test { -class HpackDecoderStatePeer { - public: - static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) { - return &state->decoder_tables_; - } - static void set_listener(HpackDecoderState* state, - HpackDecoderListener* listener) { - state->listener_ = listener; - } -}; -class HpackDecoderPeer { - public: - static HpackDecoderState* GetDecoderState(HpackDecoder* decoder) { - return &decoder->decoder_state_; - } - static HpackDecoderTables* GetDecoderTables(HpackDecoder* decoder) { - return HpackDecoderStatePeer::GetDecoderTables(GetDecoderState(decoder)); - } -}; - -namespace { - -typedef std::pair<std::string, std::string> HpackHeaderEntry; -typedef std::vector<HpackHeaderEntry> HpackHeaderEntries; - -// TODO(jamessynge): Create a ...test_utils.h file with the mock listener -// and with VerifyDynamicTableContents. -class MockHpackDecoderListener : public HpackDecoderListener { - public: - MOCK_METHOD(void, OnHeaderListStart, (), (override)); - MOCK_METHOD(void, - OnHeader, - (const std::string& name, const std::string& value), - (override)); - MOCK_METHOD(void, OnHeaderListEnd, (), (override)); - MOCK_METHOD(void, - OnHeaderErrorDetected, - (absl::string_view error_message), - (override)); -}; - -class HpackDecoderTest : public QuicheTestWithParam<bool>, - public HpackDecoderListener { - protected: - // Note that we initialize the random number generator with the same seed - // for each individual test, therefore the order in which the tests are - // executed does not effect the sequence produced by the RNG within any - // one test. - HpackDecoderTest() : decoder_(this, 4096) { - fragment_the_hpack_block_ = GetParam(); - } - ~HpackDecoderTest() override = default; - - void OnHeaderListStart() override { - ASSERT_FALSE(saw_start_); - ASSERT_FALSE(saw_end_); - saw_start_ = true; - header_entries_.clear(); - } - - // Called for each header name-value pair that is decoded, in the order they - // appear in the HPACK block. Multiple values for a given key will be emitted - // as multiple calls to OnHeader. - void OnHeader(const std::string& name, const std::string& value) override { - ASSERT_TRUE(saw_start_); - ASSERT_FALSE(saw_end_); - header_entries_.emplace_back(name, value); - } - - // OnHeaderBlockEnd is called after successfully decoding an HPACK block. Will - // only be called once per block, even if it extends into CONTINUATION frames. - // A callback method which notifies when the parser finishes handling a - // header block (i.e. the containing frame has the END_STREAM flag set). - // Also indicates the total number of bytes in this block. - void OnHeaderListEnd() override { - ASSERT_TRUE(saw_start_); - ASSERT_FALSE(saw_end_); - ASSERT_TRUE(error_messages_.empty()); - saw_end_ = true; - } - - // OnHeaderErrorDetected is called if an error is detected while decoding. - // error_message may be used in a GOAWAY frame as the Opaque Data. - void OnHeaderErrorDetected(absl::string_view error_message) override { - ASSERT_TRUE(saw_start_); - error_messages_.push_back(std::string(error_message)); - // No further callbacks should be made at this point, so replace 'this' as - // the listener with mock_listener_, which is a strict mock, so will - // generate an error for any calls. - HpackDecoderStatePeer::set_listener( - HpackDecoderPeer::GetDecoderState(&decoder_), &mock_listener_); - } - - AssertionResult DecodeBlock(absl::string_view block) { - HTTP2_VLOG(1) << "HpackDecoderTest::DecodeBlock"; - - VERIFY_FALSE(decoder_.DetectError()); - VERIFY_TRUE(error_messages_.empty()); - VERIFY_FALSE(saw_start_); - VERIFY_FALSE(saw_end_); - header_entries_.clear(); - - VERIFY_FALSE(decoder_.DetectError()); - VERIFY_TRUE(decoder_.StartDecodingBlock()); - VERIFY_FALSE(decoder_.DetectError()); - - if (fragment_the_hpack_block_) { - // See note in ctor regarding RNG. - while (!block.empty()) { - size_t fragment_size = random_.RandomSizeSkewedLow(block.size()); - DecodeBuffer db(block.substr(0, fragment_size)); - VERIFY_TRUE(decoder_.DecodeFragment(&db)); - VERIFY_EQ(0u, db.Remaining()); - block.remove_prefix(fragment_size); - } - } else { - DecodeBuffer db(block); - VERIFY_TRUE(decoder_.DecodeFragment(&db)); - VERIFY_EQ(0u, db.Remaining()); - } - VERIFY_FALSE(decoder_.DetectError()); - - VERIFY_TRUE(decoder_.EndDecodingBlock()); - if (saw_end_) { - VERIFY_FALSE(decoder_.DetectError()); - VERIFY_TRUE(error_messages_.empty()); - } else { - VERIFY_TRUE(decoder_.DetectError()); - VERIFY_FALSE(error_messages_.empty()); - } - - saw_start_ = saw_end_ = false; - return AssertionSuccess(); - } - - const HpackDecoderTables& GetDecoderTables() { - return *HpackDecoderPeer::GetDecoderTables(&decoder_); - } - const HpackStringPair* Lookup(size_t index) { - return GetDecoderTables().Lookup(index); - } - size_t current_header_table_size() { - return GetDecoderTables().current_header_table_size(); - } - size_t header_table_size_limit() { - return GetDecoderTables().header_table_size_limit(); - } - void set_header_table_size_limit(size_t size) { - HpackDecoderPeer::GetDecoderTables(&decoder_)->DynamicTableSizeUpdate(size); - } - - // dynamic_index is one-based, because that is the way RFC 7541 shows it. - AssertionResult VerifyEntry(size_t dynamic_index, - const char* name, - const char* value) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_NE(entry, nullptr); - VERIFY_EQ(entry->name, name); - VERIFY_EQ(entry->value, value); - return AssertionSuccess(); - } - AssertionResult VerifyNoEntry(size_t dynamic_index) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_EQ(entry, nullptr); - return AssertionSuccess(); - } - AssertionResult VerifyDynamicTableContents( - const std::vector<std::pair<const char*, const char*>>& entries) { - size_t index = 1; - for (const auto& entry : entries) { - VERIFY_SUCCESS(VerifyEntry(index, entry.first, entry.second)); - ++index; - } - VERIFY_SUCCESS(VerifyNoEntry(index)); - return AssertionSuccess(); - } - - Http2Random random_; - HpackDecoder decoder_; - testing::StrictMock<MockHpackDecoderListener> mock_listener_; - HpackHeaderEntries header_entries_; - std::vector<std::string> error_messages_; - bool fragment_the_hpack_block_; - bool saw_start_ = false; - bool saw_end_ = false; -}; -INSTANTIATE_TEST_SUITE_P(AllWays, HpackDecoderTest, ::testing::Bool()); - -// Test based on RFC 7541, section C.3: Request Examples without Huffman Coding. -// This section shows several consecutive header lists, corresponding to HTTP -// requests, on the same connection. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3 -TEST_P(HpackDecoderTest, C3_RequestExamples) { - // C.3.1 First Request - std::string hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - 41 | == Literal indexed == - | Indexed name (idx = 1) - | :authority - 0f | Literal value (len = 15) - 7777 772e 6578 616d 706c 652e 636f 6d | www.example.com - | -> :authority: - | www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":method", "GET"}, - HpackHeaderEntry{":scheme", "http"}, - HpackHeaderEntry{":path", "/"}, - HpackHeaderEntry{":authority", "www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 57) :authority: www.example.com - // Table size: 57 - ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}})); - ASSERT_EQ(57u, current_header_table_size()); - - // C.3.2 Second Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - be | == Indexed - Add == - | idx = 62 - | -> :authority: - | www.example.com - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 08 | Literal value (len = 8) - 6e6f 2d63 6163 6865 | no-cache - | -> cache-control: no-cache - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":method", "GET"}, - HpackHeaderEntry{":scheme", "http"}, - HpackHeaderEntry{":path", "/"}, - HpackHeaderEntry{":authority", "www.example.com"}, - HpackHeaderEntry{"cache-control", "no-cache"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 53) cache-control: no-cache - // [ 2] (s = 57) :authority: www.example.com - // Table size: 110 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"cache-control", "no-cache"}, {":authority", "www.example.com"}})); - ASSERT_EQ(110u, current_header_table_size()); - - // C.3.2 Third Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 87 | == Indexed - Add == - | idx = 7 - | -> :scheme: https - 85 | == Indexed - Add == - | idx = 5 - | -> :path: /index.html - bf | == Indexed - Add == - | idx = 63 - | -> :authority: - | www.example.com - 40 | == Literal indexed == - 0a | Literal name (len = 10) - 6375 7374 6f6d 2d6b 6579 | custom-key - 0c | Literal value (len = 12) - 6375 7374 6f6d 2d76 616c 7565 | custom-value - | -> custom-key: - | custom-value - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":method", "GET"}, - HpackHeaderEntry{":scheme", "https"}, - HpackHeaderEntry{":path", "/index.html"}, - HpackHeaderEntry{":authority", "www.example.com"}, - HpackHeaderEntry{"custom-key", "custom-value"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 54) custom-key: custom-value - // [ 2] (s = 53) cache-control: no-cache - // [ 3] (s = 57) :authority: www.example.com - // Table size: 164 - ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"}, - {"cache-control", "no-cache"}, - {":authority", "www.example.com"}})); - ASSERT_EQ(164u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.4 Request Examples with Huffman Coding. -// This section shows the same examples as the previous section but uses -// Huffman encoding for the literal values. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 -TEST_P(HpackDecoderTest, C4_RequestExamplesWithHuffmanEncoding) { - // C.4.1 First Request - std::string hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - 41 | == Literal indexed == - | Indexed name (idx = 1) - | :authority - 8c | Literal value (len = 12) - | Huffman encoded: - f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... - | Decoded: - | www.example.com - | -> :authority: - | www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":method", "GET"}, - HpackHeaderEntry{":scheme", "http"}, - HpackHeaderEntry{":path", "/"}, - HpackHeaderEntry{":authority", "www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 57) :authority: www.example.com - // Table size: 57 - ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}})); - ASSERT_EQ(57u, current_header_table_size()); - - // C.4.2 Second Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - be | == Indexed - Add == - | idx = 62 - | -> :authority: - | www.example.com - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 86 | Literal value (len = 6) - | Huffman encoded: - a8eb 1064 9cbf | ...d.. - | Decoded: - | no-cache - | -> cache-control: no-cache - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":method", "GET"}, - HpackHeaderEntry{":scheme", "http"}, - HpackHeaderEntry{":path", "/"}, - HpackHeaderEntry{":authority", "www.example.com"}, - HpackHeaderEntry{"cache-control", "no-cache"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 53) cache-control: no-cache - // [ 2] (s = 57) :authority: www.example.com - // Table size: 110 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"cache-control", "no-cache"}, {":authority", "www.example.com"}})); - ASSERT_EQ(110u, current_header_table_size()); - - // C.4.2 Third Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 87 | == Indexed - Add == - | idx = 7 - | -> :scheme: https - 85 | == Indexed - Add == - | idx = 5 - | -> :path: /index.html - bf | == Indexed - Add == - | idx = 63 - | -> :authority: - | www.example.com - 40 | == Literal indexed == - 88 | Literal name (len = 8) - | Huffman encoded: - 25a8 49e9 5ba9 7d7f | %.I.[.}. - | Decoded: - | custom-key - 89 | Literal value (len = 9) - | Huffman encoded: - 25a8 49e9 5bb8 e8b4 bf | %.I.[.... - | Decoded: - | custom-value - | -> custom-key: - | custom-value - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":method", "GET"}, - HpackHeaderEntry{":scheme", "https"}, - HpackHeaderEntry{":path", "/index.html"}, - HpackHeaderEntry{":authority", "www.example.com"}, - HpackHeaderEntry{"custom-key", "custom-value"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 54) custom-key: custom-value - // [ 2] (s = 53) cache-control: no-cache - // [ 3] (s = 57) :authority: www.example.com - // Table size: 164 - ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"}, - {"cache-control", "no-cache"}, - {":authority", "www.example.com"}})); - ASSERT_EQ(164u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.5: Response Examples without Huffman -// Coding. This section shows several consecutive header lists, corresponding -// to HTTP responses, on the same connection. The HTTP/2 setting parameter -// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing -// some evictions to occur. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.5 -TEST_P(HpackDecoderTest, C5_ResponseExamples) { - set_header_table_size_limit(256); - - // C.5.1 First Response - // - // Header list to encode: - // - // :status: 302 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - std::string hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 32 | 302 - | -> :status: 302 - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 07 | Literal value (len = 7) - 7072 6976 6174 65 | private - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - 6e | == Literal indexed == - | Indexed name (idx = 46) - | location - 17 | Literal value (len = 23) - 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam - 706c 652e 636f 6d | ple.com - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":status", "302"}, - HpackHeaderEntry{"cache-control", "private"}, - HpackHeaderEntry{"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{"location", "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 63) location: https://www.example.com - // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 3] (s = 52) cache-control: private - // [ 4] (s = 42) :status: 302 - // Table size: 222 - ASSERT_TRUE( - VerifyDynamicTableContents({{"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}, - {":status", "302"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.2 Second Response - // - // The (":status", "302") header field is evicted from the dynamic table to - // free space to allow adding the (":status", "307") header field. - // - // Header list to encode: - // - // :status: 307 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 37 | 307 - | - evict: :status: 302 - | -> :status: 307 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - c0 | == Indexed - Add == - | idx = 64 - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - bf | == Indexed - Add == - | idx = 63 - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":status", "307"}, - HpackHeaderEntry{"cache-control", "private"}, - HpackHeaderEntry{"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{"location", "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 42) :status: 307 - // [ 2] (s = 63) location: https://www.example.com - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 4] (s = 52) cache-control: private - // Table size: 222 - - ASSERT_TRUE( - VerifyDynamicTableContents({{":status", "307"}, - {"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.3 Third Response - // - // Several header fields are evicted from the dynamic table during the - // processing of this header list. - // - // Header list to encode: - // - // :status: 200 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:22 GMT - // location: https://www.example.com - // content-encoding: gzip - // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1 - hpack_block = HpackExampleToStringOrDie(R"( - 88 | == Indexed - Add == - | idx = 8 - | -> :status: 200 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3220 474d 54 | 20:13:22 GMT - | - evict: cache-control: - | private - | -> date: Mon, 21 Oct 2013 - | 20:13:22 GMT - c0 | == Indexed - Add == - | idx = 64 - | -> location: - | https://www.example.com - 5a | == Literal indexed == - | Indexed name (idx = 26) - | content-encoding - 04 | Literal value (len = 4) - 677a 6970 | gzip - | - evict: date: Mon, 21 Oct - | 2013 20:13:21 GMT - | -> content-encoding: gzip - 77 | == Literal indexed == - | Indexed name (idx = 55) - | set-cookie - 38 | Literal value (len = 56) - 666f 6f3d 4153 444a 4b48 514b 425a 584f | foo=ASDJKHQKBZXO - 5157 454f 5049 5541 5851 5745 4f49 553b | QWEOPIUAXQWEOIU; - 206d 6178 2d61 6765 3d33 3630 303b 2076 | max-age=3600; v - 6572 7369 6f6e 3d31 | ersion=1 - | - evict: location: - | https://www.example.com - | - evict: :status: 307 - | -> set-cookie: foo=ASDJKHQ - | KBZXOQWEOPIUAXQWEOIU; ma - | x-age=3600; version=1 - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":status", "200"}, - HpackHeaderEntry{"cache-control", "private"}, - HpackHeaderEntry{"date", "Mon, 21 Oct 2013 20:13:22 GMT"}, - HpackHeaderEntry{"location", "https://www.example.com"}, - HpackHeaderEntry{"content-encoding", "gzip"}, - HpackHeaderEntry{ - "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; - // max-age=3600; version=1 - // [ 2] (s = 52) content-encoding: gzip - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT - // Table size: 215 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - {"content-encoding", "gzip"}, - {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}})); - ASSERT_EQ(215u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.6: Response Examples with Huffman Coding. -// This section shows the same examples as the previous section but uses Huffman -// encoding for the literal values. The HTTP/2 setting parameter -// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing some -// evictions to occur. The eviction mechanism uses the length of the decoded -// literal values, so the same evictions occur as in the previous section. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.6 -TEST_P(HpackDecoderTest, C6_ResponseExamplesWithHuffmanEncoding) { - set_header_table_size_limit(256); - - // C.5.1 First Response - // - // Header list to encode: - // - // :status: 302 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - std::string hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 32 | 302 - | -> :status: 302 - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 07 | Literal value (len = 7) - 7072 6976 6174 65 | private - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - 6e | == Literal indexed == - | Indexed name (idx = 46) - | location - 17 | Literal value (len = 23) - 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam - 706c 652e 636f 6d | ple.com - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":status", "302"}, - HpackHeaderEntry{"cache-control", "private"}, - HpackHeaderEntry{"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{"location", "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 63) location: https://www.example.com - // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 3] (s = 52) cache-control: private - // [ 4] (s = 42) :status: 302 - // Table size: 222 - ASSERT_TRUE( - VerifyDynamicTableContents({{"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}, - {":status", "302"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.2 Second Response - // - // The (":status", "302") header field is evicted from the dynamic table to - // free space to allow adding the (":status", "307") header field. - // - // Header list to encode: - // - // :status: 307 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 37 | 307 - | - evict: :status: 302 - | -> :status: 307 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - c0 | == Indexed - Add == - | idx = 64 - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - bf | == Indexed - Add == - | idx = 63 - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":status", "307"}, - HpackHeaderEntry{"cache-control", "private"}, - HpackHeaderEntry{"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{"location", "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 42) :status: 307 - // [ 2] (s = 63) location: https://www.example.com - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 4] (s = 52) cache-control: private - // Table size: 222 - ASSERT_TRUE( - VerifyDynamicTableContents({{":status", "307"}, - {"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.3 Third Response - // - // Several header fields are evicted from the dynamic table during the - // processing of this header list. - // - // Header list to encode: - // - // :status: 200 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:22 GMT - // location: https://www.example.com - // content-encoding: gzip - // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1 - hpack_block = HpackExampleToStringOrDie(R"( - 88 | == Indexed - Add == - | idx = 8 - | -> :status: 200 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3220 474d 54 | 20:13:22 GMT - | - evict: cache-control: - | private - | -> date: Mon, 21 Oct 2013 - | 20:13:22 GMT - c0 | == Indexed - Add == - | idx = 64 - | -> location: - | https://www.example.com - 5a | == Literal indexed == - | Indexed name (idx = 26) - | content-encoding - 04 | Literal value (len = 4) - 677a 6970 | gzip - | - evict: date: Mon, 21 Oct - | 2013 20:13:21 GMT - | -> content-encoding: gzip - 77 | == Literal indexed == - | Indexed name (idx = 55) - | set-cookie - 38 | Literal value (len = 56) - 666f 6f3d 4153 444a 4b48 514b 425a 584f | foo=ASDJKHQKBZXO - 5157 454f 5049 5541 5851 5745 4f49 553b | QWEOPIUAXQWEOIU; - 206d 6178 2d61 6765 3d33 3630 303b 2076 | max-age=3600; v - 6572 7369 6f6e 3d31 | ersion=1 - | - evict: location: - | https://www.example.com - | - evict: :status: 307 - | -> set-cookie: foo=ASDJKHQ - | KBZXOQWEOPIUAXQWEOIU; ma - | x-age=3600; version=1 - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{":status", "200"}, - HpackHeaderEntry{"cache-control", "private"}, - HpackHeaderEntry{"date", "Mon, 21 Oct 2013 20:13:22 GMT"}, - HpackHeaderEntry{"location", "https://www.example.com"}, - HpackHeaderEntry{"content-encoding", "gzip"}, - HpackHeaderEntry{ - "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; - // max-age=3600; version=1 - // [ 2] (s = 52) content-encoding: gzip - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT - // Table size: 215 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - {"content-encoding", "gzip"}, - {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}})); - ASSERT_EQ(215u, current_header_table_size()); -} - -// Confirm that the table size can be changed, but at most twice. -TEST_P(HpackDecoderTest, ProcessesOptionalTableSizeUpdates) { - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - // One update allowed. - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(3000); - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(3000u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - // Two updates allowed. - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(2000); - hbb.AppendDynamicTableSizeUpdate(2500); - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(2500u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - // A third update in the same HPACK block is rejected, so the final - // size is 1000, not 500. - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(1500); - hbb.AppendDynamicTableSizeUpdate(1000); - hbb.AppendDynamicTableSizeUpdate(500); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(HpackDecodingError::kDynamicTableSizeUpdateNotAllowed, - decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - Eq("Dynamic table size update not allowed")); - EXPECT_EQ(1000u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - // An error has been detected, so calls to HpackDecoder::DecodeFragment - // should return immediately. - DecodeBuffer db("\x80"); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_EQ(0u, db.Offset()); - EXPECT_EQ(1u, error_messages_.size()); -} - -// Confirm that the table size can be changed when required, but at most twice. -TEST_P(HpackDecoderTest, ProcessesRequiredTableSizeUpdate) { - EXPECT_EQ(4096u, decoder_.GetCurrentHeaderTableSizeSetting()); - // One update required, two allowed, one provided, followed by a header. - decoder_.ApplyHeaderTableSizeSetting(1024); - decoder_.ApplyHeaderTableSizeSetting(2048); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - EXPECT_EQ(2048u, decoder_.GetCurrentHeaderTableSizeSetting()); - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(1024); - hbb.AppendIndexedHeader(4); // :path: / - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_THAT(header_entries_, - ElementsAreArray({HpackHeaderEntry{":path", "/"}})); - EXPECT_EQ(1024u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - } - // One update required, two allowed, two provided, followed by a header. - decoder_.ApplyHeaderTableSizeSetting(1000); - decoder_.ApplyHeaderTableSizeSetting(1500); - EXPECT_EQ(1500u, decoder_.GetCurrentHeaderTableSizeSetting()); - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(500); - hbb.AppendDynamicTableSizeUpdate(1250); - hbb.AppendIndexedHeader(5); // :path: /index.html - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_THAT(header_entries_, - ElementsAreArray({HpackHeaderEntry{":path", "/index.html"}})); - EXPECT_EQ(1250u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - } - // One update required, two allowed, three provided, followed by a header. - // The third update is rejected, so the final size is 1000, not 500. - decoder_.ApplyHeaderTableSizeSetting(500); - decoder_.ApplyHeaderTableSizeSetting(1000); - EXPECT_EQ(1000u, decoder_.GetCurrentHeaderTableSizeSetting()); - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(200); - hbb.AppendDynamicTableSizeUpdate(700); - hbb.AppendDynamicTableSizeUpdate(900); - hbb.AppendIndexedHeader(5); // Not decoded. - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(HpackDecodingError::kDynamicTableSizeUpdateNotAllowed, - decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - Eq("Dynamic table size update not allowed")); - EXPECT_EQ(700u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - EXPECT_EQ(1000u, decoder_.GetCurrentHeaderTableSizeSetting()); - // Now that an error has been detected, StartDecodingBlock should return - // false. - EXPECT_FALSE(decoder_.StartDecodingBlock()); -} - -// Confirm that required size updates are validated. -TEST_P(HpackDecoderTest, InvalidRequiredSizeUpdate) { - // Require a size update, but provide one that isn't small enough (must be - // zero or one, in this case). - decoder_.ApplyHeaderTableSizeSetting(1); - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(2); - EXPECT_TRUE(decoder_.StartDecodingBlock()); - DecodeBuffer db(hbb.buffer()); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_FALSE(saw_end_); - EXPECT_EQ( - HpackDecodingError::kInitialDynamicTableSizeUpdateIsAboveLowWaterMark, - decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - Eq("Initial dynamic table size update is above low water mark")); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); -} - -// Confirm that required size updates are indeed required before the end. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeEnd) { - decoder_.ApplyHeaderTableSizeSetting(1024); - EXPECT_FALSE(DecodeBlock("")); - EXPECT_EQ(HpackDecodingError::kMissingDynamicTableSizeUpdate, - decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], Eq("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); -} - -// Confirm that required size updates are indeed required before an -// indexed header. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeIndexedHeader) { - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendIndexedHeader(1); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(HpackDecodingError::kMissingDynamicTableSizeUpdate, - decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], Eq("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that required size updates are indeed required before an indexed -// header name. -// TODO(jamessynge): Move some of these to hpack_decoder_state_test.cc. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeIndexedHeaderName) { - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 2, - false, "PUT"); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(HpackDecodingError::kMissingDynamicTableSizeUpdate, - decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], Eq("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that required size updates are indeed required before a literal -// header name. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeLiteralName) { - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, - false, "name", false, "some data."); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(HpackDecodingError::kMissingDynamicTableSizeUpdate, - decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], Eq("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that an excessively long varint is detected, in this case an -// index of 127, but with lots of additional high-order 0 bits provided, -// too many to be allowed. -TEST_P(HpackDecoderTest, InvalidIndexedHeaderVarint) { - EXPECT_TRUE(decoder_.StartDecodingBlock()); - DecodeBuffer db("\xff\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x00"); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_TRUE(decoder_.DetectError()); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(HpackDecodingError::kIndexVarintError, decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - Eq("Index varint beyond implementation limit")); - EXPECT_TRUE(header_entries_.empty()); - // Now that an error has been detected, EndDecodingBlock should not succeed. - EXPECT_FALSE(decoder_.EndDecodingBlock()); -} - -// Confirm that an invalid index into the tables is detected, in this case an -// index of 0. -TEST_P(HpackDecoderTest, InvalidIndex) { - EXPECT_TRUE(decoder_.StartDecodingBlock()); - DecodeBuffer db("\x80"); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_TRUE(decoder_.DetectError()); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(HpackDecodingError::kInvalidIndex, decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - Eq("Invalid index in indexed header field representation")); - EXPECT_TRUE(header_entries_.empty()); - // Now that an error has been detected, EndDecodingBlock should not succeed. - EXPECT_FALSE(decoder_.EndDecodingBlock()); -} - -// Confirm that EndDecodingBlock detects a truncated HPACK block. -TEST_P(HpackDecoderTest, TruncatedBlock) { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(3000); - EXPECT_EQ(3u, hbb.size()); - hbb.AppendDynamicTableSizeUpdate(4000); - EXPECT_EQ(6u, hbb.size()); - // Decodes this block if the whole thing is provided. - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(4000u, header_table_size_limit()); - // Multiple times even. - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(4000u, header_table_size_limit()); - // But not if the block is truncated. - EXPECT_FALSE(DecodeBlock(hbb.buffer().substr(0, hbb.size() - 1))); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(HpackDecodingError::kTruncatedBlock, decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - Eq("Block ends in the middle of an instruction")); - // The first update was decoded. - EXPECT_EQ(3000u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that an oversized string is detected, ending decoding. -TEST_P(HpackDecoderTest, OversizeStringDetected) { - HpackBlockBuilder hbb; - hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, - false, "name", false, "some data."); - hbb.AppendLiteralNameAndValue(HpackEntryType::kUnindexedLiteralHeader, false, - "name2", false, "longer data"); - - // Normally able to decode this block. - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_THAT(header_entries_, - ElementsAreArray({HpackHeaderEntry{"name", "some data."}, - HpackHeaderEntry{"name2", "longer data"}})); - - // But not if the maximum size of strings is less than the longest string. - decoder_.set_max_string_size_bytes(10); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_THAT(header_entries_, - ElementsAreArray({HpackHeaderEntry{"name", "some data."}})); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(HpackDecodingError::kValueTooLong, decoder_.error()); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], Eq("Value length exceeds buffer limit")); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoding_error.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoding_error.cc deleted file mode 100644 index 24db30dd55d..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoding_error.cc +++ /dev/null @@ -1,51 +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/hpack/decoder/hpack_decoding_error.h" - -namespace http2 { - -// static -absl::string_view HpackDecodingErrorToString(HpackDecodingError error) { - switch (error) { - case HpackDecodingError::kOk: - return "No error detected"; - case HpackDecodingError::kIndexVarintError: - return "Index varint beyond implementation limit"; - case HpackDecodingError::kNameLengthVarintError: - return "Name length varint beyond implementation limit"; - case HpackDecodingError::kValueLengthVarintError: - return "Value length varint beyond implementation limit"; - case HpackDecodingError::kNameTooLong: - return "Name length exceeds buffer limit"; - case HpackDecodingError::kValueTooLong: - return "Value length exceeds buffer limit"; - case HpackDecodingError::kNameHuffmanError: - return "Name Huffman encoding error"; - case HpackDecodingError::kValueHuffmanError: - return "Value Huffman encoding error"; - case HpackDecodingError::kMissingDynamicTableSizeUpdate: - return "Missing dynamic table size update"; - case HpackDecodingError::kInvalidIndex: - return "Invalid index in indexed header field representation"; - case HpackDecodingError::kInvalidNameIndex: - return "Invalid index in literal header field with indexed name " - "representation"; - case HpackDecodingError::kDynamicTableSizeUpdateNotAllowed: - return "Dynamic table size update not allowed"; - case HpackDecodingError::kInitialDynamicTableSizeUpdateIsAboveLowWaterMark: - return "Initial dynamic table size update is above low water mark"; - case HpackDecodingError::kDynamicTableSizeUpdateIsAboveAcknowledgedSetting: - return "Dynamic table size update is above acknowledged setting"; - case HpackDecodingError::kTruncatedBlock: - return "Block ends in the middle of an instruction"; - case HpackDecodingError::kFragmentTooLong: - return "Incoming data fragment exceeds buffer limit"; - case HpackDecodingError::kCompressedHeaderSizeExceedsLimit: - return "Total compressed HPACK data size exceeds limit"; - } - return "invalid HpackDecodingError value"; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoding_error.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoding_error.h deleted file mode 100644 index 0b9708715f3..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoding_error.h +++ /dev/null @@ -1,51 +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_HPACK_DECODER_HPACK_DECODING_ERROR_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODING_ERROR_H_ - -#include "absl/strings/string_view.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -enum class HpackDecodingError { - // No error detected so far. - kOk, - // Varint beyond implementation limit. - kIndexVarintError, - kNameLengthVarintError, - kValueLengthVarintError, - // String literal length exceeds buffer limit. - kNameTooLong, - kValueTooLong, - // Error in Huffman encoding. - kNameHuffmanError, - kValueHuffmanError, - // Next instruction should have been a dynamic table size update. - kMissingDynamicTableSizeUpdate, - // Invalid index in indexed header field representation. - kInvalidIndex, - // Invalid index in literal header field with indexed name representation. - kInvalidNameIndex, - // Dynamic table size update not allowed. - kDynamicTableSizeUpdateNotAllowed, - // Initial dynamic table size update is above low water mark. - kInitialDynamicTableSizeUpdateIsAboveLowWaterMark, - // Dynamic table size update is above acknowledged setting. - kDynamicTableSizeUpdateIsAboveAcknowledgedSetting, - // HPACK block ends in the middle of an instruction. - kTruncatedBlock, - // Incoming data fragment exceeds buffer limit. - kFragmentTooLong, - // Total compressed HPACK data size exceeds limit. - kCompressedHeaderSizeExceedsLimit, -}; - -QUICHE_EXPORT_PRIVATE absl::string_view HpackDecodingErrorToString( - HpackDecodingError error); - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODING_ERROR_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc deleted file mode 100644 index de7d2e2edac..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc +++ /dev/null @@ -1,301 +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/hpack/decoder/hpack_entry_collector.h" - -#include "absl/strings/str_cat.h" -#include "http2/hpack/decoder/hpack_string_collector.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::AssertionResult; - -namespace http2 { -namespace test { -namespace { - -const HpackEntryType kInvalidHeaderType = static_cast<HpackEntryType>(99); -const size_t kInvalidIndex = 99999999; - -} // namespace - -HpackEntryCollector::HpackEntryCollector() { - Clear(); -} - -HpackEntryCollector::HpackEntryCollector(const HpackEntryCollector& other) = - default; - -HpackEntryCollector::HpackEntryCollector(HpackEntryType type, - size_t index_or_size) - : header_type_(type), index_(index_or_size), started_(true), ended_(true) {} -HpackEntryCollector::HpackEntryCollector(HpackEntryType type, - size_t index, - bool value_huffman, - const std::string& value) - : header_type_(type), - index_(index), - value_(value, value_huffman), - started_(true), - ended_(true) {} -HpackEntryCollector::HpackEntryCollector(HpackEntryType type, - bool name_huffman, - const std::string& name, - bool value_huffman, - const std::string& value) - : header_type_(type), - index_(0), - name_(name, name_huffman), - value_(value, value_huffman), - started_(true), - ended_(true) {} - -HpackEntryCollector::~HpackEntryCollector() = default; - -void HpackEntryCollector::OnIndexedHeader(size_t index) { - ASSERT_FALSE(started_); - ASSERT_TRUE(IsClear()) << ToString(); - Init(HpackEntryType::kIndexedHeader, index); - ended_ = true; -} -void HpackEntryCollector::OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) { - ASSERT_FALSE(started_); - ASSERT_TRUE(IsClear()) << ToString(); - Init(header_type, maybe_name_index); -} -void HpackEntryCollector::OnNameStart(bool huffman_encoded, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_FALSE(IsClear()); - ASSERT_TRUE(LiteralNameExpected()) << ToString(); - name_.OnStringStart(huffman_encoded, len); -} -void HpackEntryCollector::OnNameData(const char* data, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralNameExpected()) << ToString(); - ASSERT_TRUE(name_.IsInProgress()); - name_.OnStringData(data, len); -} -void HpackEntryCollector::OnNameEnd() { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralNameExpected()) << ToString(); - ASSERT_TRUE(name_.IsInProgress()); - name_.OnStringEnd(); -} -void HpackEntryCollector::OnValueStart(bool huffman_encoded, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - if (LiteralNameExpected()) { - ASSERT_TRUE(name_.HasEnded()); - } - ASSERT_TRUE(LiteralValueExpected()) << ToString(); - ASSERT_TRUE(value_.IsClear()) << value_.ToString(); - value_.OnStringStart(huffman_encoded, len); -} -void HpackEntryCollector::OnValueData(const char* data, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralValueExpected()) << ToString(); - ASSERT_TRUE(value_.IsInProgress()); - value_.OnStringData(data, len); -} -void HpackEntryCollector::OnValueEnd() { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralValueExpected()) << ToString(); - ASSERT_TRUE(value_.IsInProgress()); - value_.OnStringEnd(); - ended_ = true; -} -void HpackEntryCollector::OnDynamicTableSizeUpdate(size_t size) { - ASSERT_FALSE(started_); - ASSERT_TRUE(IsClear()) << ToString(); - Init(HpackEntryType::kDynamicTableSizeUpdate, size); - ended_ = true; -} - -void HpackEntryCollector::Clear() { - header_type_ = kInvalidHeaderType; - index_ = kInvalidIndex; - name_.Clear(); - value_.Clear(); - started_ = ended_ = false; -} -bool HpackEntryCollector::IsClear() const { - return header_type_ == kInvalidHeaderType && index_ == kInvalidIndex && - name_.IsClear() && value_.IsClear() && !started_ && !ended_; -} -bool HpackEntryCollector::IsComplete() const { - return started_ && ended_; -} -bool HpackEntryCollector::LiteralNameExpected() const { - switch (header_type_) { - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - return index_ == 0; - default: - return false; - } -} -bool HpackEntryCollector::LiteralValueExpected() const { - switch (header_type_) { - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - return true; - default: - return false; - } -} -AssertionResult HpackEntryCollector::ValidateIndexedHeader( - size_t expected_index) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(HpackEntryType::kIndexedHeader, header_type_); - VERIFY_EQ(expected_index, index_); - return ::testing::AssertionSuccess(); -} -AssertionResult HpackEntryCollector::ValidateLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - absl::string_view expected_value) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(expected_type, header_type_); - VERIFY_NE(0u, expected_index); - VERIFY_EQ(expected_index, index_); - VERIFY_TRUE(name_.IsClear()); - VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman)); - return ::testing::AssertionSuccess(); -} -AssertionResult HpackEntryCollector::ValidateLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - absl::string_view expected_name, - bool expected_value_huffman, - absl::string_view expected_value) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(expected_type, header_type_); - VERIFY_EQ(0u, index_); - VERIFY_SUCCESS(name_.Collected(expected_name, expected_name_huffman)); - VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman)); - return ::testing::AssertionSuccess(); -} -AssertionResult HpackEntryCollector::ValidateDynamicTableSizeUpdate( - size_t size) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, header_type_); - VERIFY_EQ(index_, size); - return ::testing::AssertionSuccess(); -} - -void HpackEntryCollector::AppendToHpackBlockBuilder( - HpackBlockBuilder* hbb) const { - ASSERT_TRUE(started_ && ended_) << *this; - switch (header_type_) { - case HpackEntryType::kIndexedHeader: - hbb->AppendIndexedHeader(index_); - return; - - case HpackEntryType::kDynamicTableSizeUpdate: - hbb->AppendDynamicTableSizeUpdate(index_); - return; - - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - ASSERT_TRUE(value_.HasEnded()) << *this; - if (index_ != 0) { - QUICHE_CHECK(name_.IsClear()); - hbb->AppendNameIndexAndLiteralValue(header_type_, index_, - value_.huffman_encoded, value_.s); - } else { - QUICHE_CHECK(name_.HasEnded()) << *this; - hbb->AppendLiteralNameAndValue(header_type_, name_.huffman_encoded, - name_.s, value_.huffman_encoded, - value_.s); - } - return; - - default: - ADD_FAILURE() << *this; - } -} - -std::string HpackEntryCollector::ToString() const { - std::string result("Type="); - switch (header_type_) { - case HpackEntryType::kIndexedHeader: - result += "IndexedHeader"; - break; - case HpackEntryType::kDynamicTableSizeUpdate: - result += "DynamicTableSizeUpdate"; - break; - case HpackEntryType::kIndexedLiteralHeader: - result += "IndexedLiteralHeader"; - break; - case HpackEntryType::kUnindexedLiteralHeader: - result += "UnindexedLiteralHeader"; - break; - case HpackEntryType::kNeverIndexedLiteralHeader: - result += "NeverIndexedLiteralHeader"; - break; - default: - if (header_type_ == kInvalidHeaderType) { - result += "<unset>"; - } else { - absl::StrAppend(&result, header_type_); - } - } - if (index_ != 0) { - absl::StrAppend(&result, " Index=", index_); - } - if (!name_.IsClear()) { - absl::StrAppend(&result, " Name", name_.ToString()); - } - if (!value_.IsClear()) { - absl::StrAppend(&result, " Value", value_.ToString()); - } - if (!started_) { - EXPECT_FALSE(ended_); - absl::StrAppend(&result, " !started"); - } else if (!ended_) { - absl::StrAppend(&result, " !ended"); - } else { - absl::StrAppend(&result, " Complete"); - } - return result; -} - -void HpackEntryCollector::Init(HpackEntryType type, size_t maybe_index) { - ASSERT_TRUE(IsClear()) << ToString(); - header_type_ = type; - index_ = maybe_index; - started_ = true; -} - -bool operator==(const HpackEntryCollector& a, const HpackEntryCollector& b) { - return a.name() == b.name() && a.value() == b.value() && - a.index() == b.index() && a.header_type() == b.header_type() && - a.started() == b.started() && a.ended() == b.ended(); -} -bool operator!=(const HpackEntryCollector& a, const HpackEntryCollector& b) { - return !(a == b); -} - -std::ostream& operator<<(std::ostream& out, const HpackEntryCollector& v) { - return out << v.ToString(); -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.h deleted file mode 100644 index cbce8dfc01e..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.h +++ /dev/null @@ -1,155 +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_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_ - -// HpackEntryCollector records calls to HpackEntryDecoderListener in support -// of tests of HpackEntryDecoder, or which use it. Can only record the callbacks -// for the decoding of a single entry; call Clear() between decoding successive -// entries or use a distinct HpackEntryCollector for each entry. - -#include <stddef.h> - -#include <iosfwd> -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "http2/hpack/decoder/hpack_string_collector.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/hpack/tools/hpack_block_builder.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class HpackEntryCollector : public HpackEntryDecoderListener { - public: - HpackEntryCollector(); - HpackEntryCollector(const HpackEntryCollector& other); - - // These next three constructors are intended for use in tests that create - // an HpackEntryCollector "manually", and then compare it against another - // that is populated via calls to the HpackEntryDecoderListener methods. - HpackEntryCollector(HpackEntryType type, size_t index_or_size); - HpackEntryCollector(HpackEntryType type, - size_t index, - bool value_huffman, - const std::string& value); - HpackEntryCollector(HpackEntryType type, - bool name_huffman, - const std::string& name, - bool value_huffman, - const std::string& value); - - ~HpackEntryCollector() override; - - // Methods defined by HpackEntryDecoderListener. - void OnIndexedHeader(size_t index) override; - void OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - void OnDynamicTableSizeUpdate(size_t size) override; - - // Clears the fields of the collector so that it is ready to start collecting - // another HPACK block entry. - void Clear(); - - // Is the collector ready to start collecting another HPACK block entry. - bool IsClear() const; - - // Has a complete entry been collected? - bool IsComplete() const; - - // Based on the HpackEntryType, is a literal name expected? - bool LiteralNameExpected() const; - - // Based on the HpackEntryType, is a literal value expected? - bool LiteralValueExpected() const; - - // Returns success if collected an Indexed Header (i.e. OnIndexedHeader was - // called). - ::testing::AssertionResult ValidateIndexedHeader(size_t expected_index) const; - - // Returns success if collected a Header with an indexed name and literal - // value (i.e. OnStartLiteralHeader was called with a non-zero index for - // the name, which must match expected_index). - ::testing::AssertionResult ValidateLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - absl::string_view expected_value) const; - - // Returns success if collected a Header with an literal name and literal - // value. - ::testing::AssertionResult ValidateLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - absl::string_view expected_name, - bool expected_value_huffman, - absl::string_view expected_value) const; - - // Returns success if collected a Dynamic Table Size Update, - // with the specified size. - ::testing::AssertionResult ValidateDynamicTableSizeUpdate( - size_t expected_size) const; - - void set_header_type(HpackEntryType v) { header_type_ = v; } - HpackEntryType header_type() const { return header_type_; } - - void set_index(size_t v) { index_ = v; } - size_t index() const { return index_; } - - void set_name(const HpackStringCollector& v) { name_ = v; } - const HpackStringCollector& name() const { return name_; } - - void set_value(const HpackStringCollector& v) { value_ = v; } - const HpackStringCollector& value() const { return value_; } - - void set_started(bool v) { started_ = v; } - bool started() const { return started_; } - - void set_ended(bool v) { ended_ = v; } - bool ended() const { return ended_; } - - void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const; - - // Returns a debug string. - std::string ToString() const; - - private: - void Init(HpackEntryType type, size_t maybe_index); - - HpackEntryType header_type_; - size_t index_; - - HpackStringCollector name_; - HpackStringCollector value_; - - // True if has received a call to an HpackEntryDecoderListener method - // indicating the start of decoding an HPACK entry; for example, - // OnIndexedHeader set it true, but OnNameStart does not change it. - bool started_ = false; - - // True if has received a call to an HpackEntryDecoderListener method - // indicating the end of decoding an HPACK entry; for example, - // OnIndexedHeader and OnValueEnd both set it true, but OnNameEnd does - // not change it. - bool ended_ = false; -}; - -bool operator==(const HpackEntryCollector& a, const HpackEntryCollector& b); -bool operator!=(const HpackEntryCollector& a, const HpackEntryCollector& b); -std::ostream& operator<<(std::ostream& out, const HpackEntryCollector& v); - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc deleted file mode 100644 index 13022484937..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc +++ /dev/null @@ -1,295 +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/hpack/decoder/hpack_entry_decoder.h" - -#include <stddef.h> - -#include <cstdint> - -#include "absl/base/macros.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 "http2/platform/api/http2_logging.h" - -namespace http2 { -namespace { -// Converts calls from HpackStringDecoder when decoding a header name into the -// appropriate HpackEntryDecoderListener::OnName* calls. -class NameDecoderListener { - public: - explicit NameDecoderListener(HpackEntryDecoderListener* listener) - : listener_(listener) {} - bool OnStringStart(bool huffman_encoded, size_t len) { - listener_->OnNameStart(huffman_encoded, len); - return true; - } - void OnStringData(const char* data, size_t len) { - listener_->OnNameData(data, len); - } - void OnStringEnd() { listener_->OnNameEnd(); } - - private: - HpackEntryDecoderListener* listener_; -}; - -// Converts calls from HpackStringDecoder when decoding a header value into -// the appropriate HpackEntryDecoderListener::OnValue* calls. -class ValueDecoderListener { - public: - explicit ValueDecoderListener(HpackEntryDecoderListener* listener) - : listener_(listener) {} - bool OnStringStart(bool huffman_encoded, size_t len) { - listener_->OnValueStart(huffman_encoded, len); - return true; - } - void OnStringData(const char* data, size_t len) { - listener_->OnValueData(data, len); - } - void OnStringEnd() { listener_->OnValueEnd(); } - - private: - HpackEntryDecoderListener* listener_; -}; -} // namespace - -DecodeStatus HpackEntryDecoder::Start(DecodeBuffer* db, - HpackEntryDecoderListener* listener) { - QUICHE_DCHECK(db != nullptr); - QUICHE_DCHECK(listener != nullptr); - QUICHE_DCHECK(db->HasData()); - DecodeStatus status = entry_type_decoder_.Start(db); - switch (status) { - case DecodeStatus::kDecodeDone: - // The type of the entry and its varint fit into the current decode - // buffer. - if (entry_type_decoder_.entry_type() == HpackEntryType::kIndexedHeader) { - // The entry consists solely of the entry type and varint. - // This is by far the most common case in practice. - listener->OnIndexedHeader(entry_type_decoder_.varint()); - return DecodeStatus::kDecodeDone; - } - state_ = EntryDecoderState::kDecodedType; - return Resume(db, listener); - case DecodeStatus::kDecodeInProgress: - // Hit the end of the decode buffer before fully decoding - // the entry type and varint. - QUICHE_DCHECK_EQ(0u, db->Remaining()); - state_ = EntryDecoderState::kResumeDecodingType; - return status; - case DecodeStatus::kDecodeError: - HTTP2_CODE_COUNT_N(decompress_failure_3, 11, 23); - error_ = HpackDecodingError::kIndexVarintError; - // The varint must have been invalid (too long). - return status; - } - - HTTP2_BUG(http2_bug_63_1) << "Unreachable"; - return DecodeStatus::kDecodeError; -} - -DecodeStatus HpackEntryDecoder::Resume(DecodeBuffer* db, - HpackEntryDecoderListener* listener) { - QUICHE_DCHECK(db != nullptr); - QUICHE_DCHECK(listener != nullptr); - - DecodeStatus status; - - do { - switch (state_) { - case EntryDecoderState::kResumeDecodingType: - // entry_type_decoder_ returned kDecodeInProgress when last called. - HTTP2_DVLOG(1) << "kResumeDecodingType: db->Remaining=" - << db->Remaining(); - status = entry_type_decoder_.Resume(db); - if (status == DecodeStatus::kDecodeError) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 12, 23); - error_ = HpackDecodingError::kIndexVarintError; - } - if (status != DecodeStatus::kDecodeDone) { - return status; - } - state_ = EntryDecoderState::kDecodedType; - ABSL_FALLTHROUGH_INTENDED; - - case EntryDecoderState::kDecodedType: - // entry_type_decoder_ returned kDecodeDone, now need to decide how - // to proceed. - HTTP2_DVLOG(1) << "kDecodedType: db->Remaining=" << db->Remaining(); - if (DispatchOnType(listener)) { - // All done. - return DecodeStatus::kDecodeDone; - } - continue; - - case EntryDecoderState::kStartDecodingName: - HTTP2_DVLOG(1) << "kStartDecodingName: db->Remaining=" - << db->Remaining(); - { - NameDecoderListener ncb(listener); - status = string_decoder_.Start(db, &ncb); - } - if (status != DecodeStatus::kDecodeDone) { - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the name's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingName; - if (status == DecodeStatus::kDecodeError) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 13, 23); - error_ = HpackDecodingError::kNameLengthVarintError; - } - return status; - } - state_ = EntryDecoderState::kStartDecodingValue; - ABSL_FALLTHROUGH_INTENDED; - - case EntryDecoderState::kStartDecodingValue: - HTTP2_DVLOG(1) << "kStartDecodingValue: db->Remaining=" - << db->Remaining(); - { - ValueDecoderListener vcb(listener); - status = string_decoder_.Start(db, &vcb); - } - if (status == DecodeStatus::kDecodeError) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 14, 23); - error_ = HpackDecodingError::kValueLengthVarintError; - } - if (status == DecodeStatus::kDecodeDone) { - // Done with decoding the literal value, so we've reached the - // end of the header entry. - return status; - } - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the value's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingValue; - return status; - - case EntryDecoderState::kResumeDecodingName: - // The literal name was split across decode buffers. - HTTP2_DVLOG(1) << "kResumeDecodingName: db->Remaining=" - << db->Remaining(); - { - NameDecoderListener ncb(listener); - status = string_decoder_.Resume(db, &ncb); - } - if (status != DecodeStatus::kDecodeDone) { - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the name's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingName; - if (status == DecodeStatus::kDecodeError) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 15, 23); - error_ = HpackDecodingError::kNameLengthVarintError; - } - return status; - } - state_ = EntryDecoderState::kStartDecodingValue; - break; - - case EntryDecoderState::kResumeDecodingValue: - // The literal value was split across decode buffers. - HTTP2_DVLOG(1) << "kResumeDecodingValue: db->Remaining=" - << db->Remaining(); - { - ValueDecoderListener vcb(listener); - status = string_decoder_.Resume(db, &vcb); - } - if (status == DecodeStatus::kDecodeError) { - HTTP2_CODE_COUNT_N(decompress_failure_3, 16, 23); - error_ = HpackDecodingError::kValueLengthVarintError; - } - if (status == DecodeStatus::kDecodeDone) { - // Done with decoding the value, therefore the entry as a whole. - return status; - } - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the value's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingValue; - return status; - } - } while (true); -} - -bool HpackEntryDecoder::DispatchOnType(HpackEntryDecoderListener* listener) { - const HpackEntryType entry_type = entry_type_decoder_.entry_type(); - const uint32_t varint = static_cast<uint32_t>(entry_type_decoder_.varint()); - switch (entry_type) { - case HpackEntryType::kIndexedHeader: - // The entry consists solely of the entry type and varint. See: - // http://httpwg.org/specs/rfc7541.html#indexed.header.representation - listener->OnIndexedHeader(varint); - return true; - - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - // The entry has a literal value, and if the varint is zero also has a - // literal name preceding the value. See: - // http://httpwg.org/specs/rfc7541.html#literal.header.representation - listener->OnStartLiteralHeader(entry_type, varint); - if (varint == 0) { - state_ = EntryDecoderState::kStartDecodingName; - } else { - state_ = EntryDecoderState::kStartDecodingValue; - } - return false; - - case HpackEntryType::kDynamicTableSizeUpdate: - // The entry consists solely of the entry type and varint. FWIW, I've - // never seen this type of entry in production (primarily browser - // traffic) so if you're designing an HPACK successor someday, consider - // dropping it or giving it a much longer prefix. See: - // http://httpwg.org/specs/rfc7541.html#encoding.context.update - listener->OnDynamicTableSizeUpdate(varint); - return true; - } - - HTTP2_BUG(http2_bug_63_2) << "Unreachable, entry_type=" << entry_type; - return true; -} - -void HpackEntryDecoder::OutputDebugString(std::ostream& out) const { - out << "HpackEntryDecoder(state=" << state_ << ", " << entry_type_decoder_ - << ", " << string_decoder_ << ")"; -} - -std::string HpackEntryDecoder::DebugString() const { - std::stringstream s; - s << *this; - return s.str(); -} - -std::ostream& operator<<(std::ostream& out, const HpackEntryDecoder& v) { - v.OutputDebugString(out); - return out; -} - -std::ostream& operator<<(std::ostream& out, - HpackEntryDecoder::EntryDecoderState state) { - typedef HpackEntryDecoder::EntryDecoderState EntryDecoderState; - switch (state) { - case EntryDecoderState::kResumeDecodingType: - return out << "kResumeDecodingType"; - case EntryDecoderState::kDecodedType: - return out << "kDecodedType"; - case EntryDecoderState::kStartDecodingName: - return out << "kStartDecodingName"; - case EntryDecoderState::kResumeDecodingName: - return out << "kResumeDecodingName"; - case EntryDecoderState::kStartDecodingValue: - return out << "kStartDecodingValue"; - case EntryDecoderState::kResumeDecodingValue: - return out << "kResumeDecodingValue"; - } - return out << static_cast<int>(state); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.h deleted file mode 100644 index 256e7c28f40..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.h +++ /dev/null @@ -1,91 +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_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ - -// HpackEntryDecoder decodes a single HPACK entry (i.e. one header or one -// dynamic table size update), in a resumable fashion. The first call, Start(), -// must provide a non-empty decode buffer. Continue with calls to Resume() if -// Start, and any subsequent calls to Resume, returns kDecodeInProgress. - -#include <string> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/hpack/decoder/hpack_decoding_error.h" -#include "http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "http2/hpack/decoder/hpack_entry_type_decoder.h" -#include "http2/hpack/decoder/hpack_string_decoder.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE HpackEntryDecoder { - public: - enum class EntryDecoderState { - // Have started decoding the type/varint, but didn't finish on the previous - // attempt. Next state is kResumeDecodingType or kDecodedType. - kResumeDecodingType, - - // Have just finished decoding the type/varint. Final state if the type is - // kIndexedHeader or kDynamicTableSizeUpdate. Otherwise, the next state is - // kStartDecodingName (if the varint is 0), else kStartDecodingValue. - kDecodedType, - - // Ready to start decoding the literal name of a header entry. Next state - // is kResumeDecodingName (if the name is split across decode buffers), - // else kStartDecodingValue. - kStartDecodingName, - - // Resume decoding the literal name of a header that is split across decode - // buffers. - kResumeDecodingName, - - // Ready to start decoding the literal value of a header entry. Final state - // if the value string is entirely in the decode buffer, else the next state - // is kResumeDecodingValue. - kStartDecodingValue, - - // Resume decoding the literal value of a header that is split across decode - // buffers. - kResumeDecodingValue, - }; - - // Only call when the decode buffer has data (i.e. HpackBlockDecoder must - // not call until there is data). - DecodeStatus Start(DecodeBuffer* db, HpackEntryDecoderListener* listener); - - // Only call Resume if the previous call (Start or Resume) returned - // kDecodeInProgress; Resume is also called from Start when it has succeeded - // in decoding the entry type and its varint. - DecodeStatus Resume(DecodeBuffer* db, HpackEntryDecoderListener* listener); - - // Return error code after decoding error occurred. - HpackDecodingError error() const { return error_; } - - std::string DebugString() const; - void OutputDebugString(std::ostream& out) const; - - private: - // Implements handling state kDecodedType. - bool DispatchOnType(HpackEntryDecoderListener* listener); - - HpackEntryTypeDecoder entry_type_decoder_; - HpackStringDecoder string_decoder_; - EntryDecoderState state_ = EntryDecoderState(); - HpackDecodingError error_ = HpackDecodingError::kOk; -}; - -QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackEntryDecoder& v); -QUICHE_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& out, - HpackEntryDecoder::EntryDecoderState state); - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.cc deleted file mode 100644 index 994ffb33b20..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.cc +++ /dev/null @@ -1,81 +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/hpack/decoder/hpack_entry_decoder_listener.h" - -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -void HpackEntryDecoderVLoggingListener::OnIndexedHeader(size_t index) { - HTTP2_VLOG(1) << "OnIndexedHeader, index=" << index; - if (wrapped_) { - wrapped_->OnIndexedHeader(index); - } -} - -void HpackEntryDecoderVLoggingListener::OnStartLiteralHeader( - HpackEntryType entry_type, - size_t maybe_name_index) { - HTTP2_VLOG(1) << "OnStartLiteralHeader: entry_type=" << entry_type - << ", maybe_name_index=" << maybe_name_index; - if (wrapped_) { - wrapped_->OnStartLiteralHeader(entry_type, maybe_name_index); - } -} - -void HpackEntryDecoderVLoggingListener::OnNameStart(bool huffman_encoded, - size_t len) { - HTTP2_VLOG(1) << "OnNameStart: H=" << huffman_encoded << ", len=" << len; - if (wrapped_) { - wrapped_->OnNameStart(huffman_encoded, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnNameData(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnNameData: len=" << len; - if (wrapped_) { - wrapped_->OnNameData(data, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnNameEnd() { - HTTP2_VLOG(1) << "OnNameEnd"; - if (wrapped_) { - wrapped_->OnNameEnd(); - } -} - -void HpackEntryDecoderVLoggingListener::OnValueStart(bool huffman_encoded, - size_t len) { - HTTP2_VLOG(1) << "OnValueStart: H=" << huffman_encoded << ", len=" << len; - if (wrapped_) { - wrapped_->OnValueStart(huffman_encoded, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnValueData(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnValueData: len=" << len; - if (wrapped_) { - wrapped_->OnValueData(data, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnValueEnd() { - HTTP2_VLOG(1) << "OnValueEnd"; - if (wrapped_) { - wrapped_->OnValueEnd(); - } -} - -void HpackEntryDecoderVLoggingListener::OnDynamicTableSizeUpdate(size_t size) { - HTTP2_VLOG(1) << "OnDynamicTableSizeUpdate: size=" << size; - if (wrapped_) { - wrapped_->OnDynamicTableSizeUpdate(size); - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.h deleted file mode 100644 index 062a00318d3..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.h +++ /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. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_ - -// Defines HpackEntryDecoderListener, the base class of listeners that -// HpackEntryDecoder calls. Also defines HpackEntryDecoderVLoggingListener -// which logs before calling another HpackEntryDecoderListener implementation. - -#include <stddef.h> - -#include "http2/hpack/http2_hpack_constants.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE HpackEntryDecoderListener { - public: - virtual ~HpackEntryDecoderListener() {} - - // Called when an indexed header (i.e. one in the static or dynamic table) has - // been decoded from an HPACK block. index is supposed to be non-zero, but - // that has not been checked by the caller. - virtual void OnIndexedHeader(size_t index) = 0; - - // Called when the start of a header with a literal value, and maybe a literal - // name, has been decoded. maybe_name_index is zero if the header has a - // literal name, else it is a reference into the static or dynamic table, from - // which the name should be determined. When the name is literal, the next - // call will be to OnNameStart; else it will be to OnValueStart. entry_type - // indicates whether the peer has added the entry to its dynamic table, and - // whether a proxy is permitted to do so when forwarding the entry. - virtual void OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) = 0; - - // Called when the encoding (Huffman compressed or plain text) and the encoded - // length of a literal name has been decoded. OnNameData will be called next, - // and repeatedly until the sum of lengths passed to OnNameData is len. - virtual void OnNameStart(bool huffman_encoded, size_t len) = 0; - - // Called when len bytes of an encoded header name have been decoded. - virtual void OnNameData(const char* data, size_t len) = 0; - - // Called after the entire name has been passed to OnNameData. - // OnValueStart will be called next. - virtual void OnNameEnd() = 0; - - // Called when the encoding (Huffman compressed or plain text) and the encoded - // length of a literal value has been decoded. OnValueData will be called - // next, and repeatedly until the sum of lengths passed to OnValueData is len. - virtual void OnValueStart(bool huffman_encoded, size_t len) = 0; - - // Called when len bytes of an encoded header value have been decoded. - virtual void OnValueData(const char* data, size_t len) = 0; - - // Called after the entire value has been passed to OnValueData, marking the - // end of a header entry with a literal value, and maybe a literal name. - virtual void OnValueEnd() = 0; - - // Called when an update to the size of the peer's dynamic table has been - // decoded. - virtual void OnDynamicTableSizeUpdate(size_t size) = 0; -}; - -class QUICHE_EXPORT_PRIVATE HpackEntryDecoderVLoggingListener - : public HpackEntryDecoderListener { - public: - HpackEntryDecoderVLoggingListener() : wrapped_(nullptr) {} - explicit HpackEntryDecoderVLoggingListener(HpackEntryDecoderListener* wrapped) - : wrapped_(wrapped) {} - ~HpackEntryDecoderVLoggingListener() override {} - - void OnIndexedHeader(size_t index) override; - void OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - void OnDynamicTableSizeUpdate(size_t size) override; - - private: - HpackEntryDecoderListener* const wrapped_; -}; - -// A no-op implementation of HpackEntryDecoderListener. -class QUICHE_EXPORT_PRIVATE HpackEntryDecoderNoOpListener - : public HpackEntryDecoderListener { - public: - ~HpackEntryDecoderNoOpListener() override {} - - void OnIndexedHeader(size_t /*index*/) override {} - void OnStartLiteralHeader(HpackEntryType /*entry_type*/, - size_t /*maybe_name_index*/) override {} - void OnNameStart(bool /*huffman_encoded*/, size_t /*len*/) override {} - void OnNameData(const char* /*data*/, size_t /*len*/) override {} - void OnNameEnd() override {} - void OnValueStart(bool /*huffman_encoded*/, size_t /*len*/) override {} - void OnValueData(const char* /*data*/, size_t /*len*/) override {} - void OnValueEnd() override {} - void OnDynamicTableSizeUpdate(size_t /*size*/) override {} -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_test.cc deleted file mode 100644 index 32eeaf412e2..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_test.cc +++ /dev/null @@ -1,208 +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/hpack/decoder/hpack_entry_decoder.h" - -// Tests of HpackEntryDecoder. - -#include <cstdint> - -#include "http2/hpack/decoder/hpack_entry_collector.h" -#include "http2/hpack/tools/hpack_block_builder.h" -#include "http2/platform/api/http2_test_helpers.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 { - -class HpackEntryDecoderTest : public RandomDecoderTest { - protected: - HpackEntryDecoderTest() : listener_(&collector_) {} - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - collector_.Clear(); - return decoder_.Start(b, &listener_); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b, &listener_); - } - - AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* db, - const Validator& validator) { - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - return RandomDecoderTest::DecodeAndValidateSeveralWays( - db, return_non_zero_on_first, validator); - } - - AssertionResult DecodeAndValidateSeveralWays(const HpackBlockBuilder& hbb, - const Validator& validator) { - DecodeBuffer db(hbb.buffer()); - return DecodeAndValidateSeveralWays(&db, validator); - } - - HpackEntryDecoder decoder_; - HpackEntryCollector collector_; - HpackEntryDecoderVLoggingListener listener_; -}; - -TEST_F(HpackEntryDecoderTest, IndexedHeader_Literals) { - { - const char input[] = {'\x82'}; // == Index 2 == - DecodeBuffer b(input); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(2)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } - collector_.Clear(); - { - const char input[] = {'\xfe'}; // == Index 126 == - DecodeBuffer b(input); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(126)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } - collector_.Clear(); - { - const char input[] = {'\xff', '\x00'}; // == Index 127 == - DecodeBuffer b(input); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(127)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -TEST_F(HpackEntryDecoderTest, IndexedHeader_Various) { - // Indices chosen to hit encoding and table boundaries. - for (const uint32_t ndx : {1, 2, 61, 62, 63, 126, 127, 254, 255, 256}) { - HpackBlockBuilder hbb; - hbb.AppendIndexedHeader(ndx); - - auto do_check = [this, ndx]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -TEST_F(HpackEntryDecoderTest, IndexedLiteralValue_Literal) { - const char input[] = - "\x7f" // == Literal indexed, name index 0x40 == - "\x01" // 2nd byte of name index (0x01 + 0x3f == 0x40) - "\x0d" // Value length (13) - "custom-header"; // Value - DecodeBuffer b(input, sizeof input - 1); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( - HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header")); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) { - const char input[] = - "\x40" // == Literal indexed == - "\x0a" // Name length (10) - "custom-key" // Name - "\x0d" // Value length (13) - "custom-header"; // Value - - DecodeBuffer b(input, sizeof input - 1); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( - HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, - "custom-header")); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -TEST_F(HpackEntryDecoderTest, DynamicTableSizeUpdate_Literal) { - // Size update, length 31. - const char input[] = "\x3f\x00"; - DecodeBuffer b(input, 2); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31)); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -class HpackLiteralEntryDecoderTest - : public HpackEntryDecoderTest, - public ::testing::WithParamInterface<HpackEntryType> { - protected: - HpackLiteralEntryDecoderTest() : entry_type_(GetParam()) {} - - const HpackEntryType entry_type_; -}; - -INSTANTIATE_TEST_SUITE_P( - AllLiteralTypes, HpackLiteralEntryDecoderTest, - testing::Values(HpackEntryType::kIndexedLiteralHeader, - HpackEntryType::kUnindexedLiteralHeader, - HpackEntryType::kNeverIndexedLiteralHeader)); - -TEST_P(HpackLiteralEntryDecoderTest, RandNameIndexAndLiteralValue) { - for (int n = 0; n < 10; n++) { - const uint32_t ndx = 1 + Random().Rand8(); - const bool value_is_huffman_encoded = (n % 2) == 0; - const std::string value = Random().RandString(Random().Rand8()); - HpackBlockBuilder hbb; - hbb.AppendNameIndexAndLiteralValue(entry_type_, ndx, - value_is_huffman_encoded, value); - auto do_check = [this, ndx, value_is_huffman_encoded, - value]() -> AssertionResult { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( - entry_type_, ndx, value_is_huffman_encoded, value)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -TEST_P(HpackLiteralEntryDecoderTest, RandLiteralNameAndValue) { - for (int n = 0; n < 10; n++) { - const bool name_is_huffman_encoded = (n & 1) == 0; - const int name_len = 1 + Random().Rand8(); - const std::string name = Random().RandString(name_len); - const bool value_is_huffman_encoded = (n & 2) == 0; - const int value_len = Random().Skewed(10); - const std::string value = Random().RandString(value_len); - HpackBlockBuilder hbb; - hbb.AppendLiteralNameAndValue(entry_type_, name_is_huffman_encoded, name, - value_is_huffman_encoded, value); - auto do_check = [this, name_is_huffman_encoded, name, - value_is_huffman_encoded, value]() -> AssertionResult { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( - entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded, - value)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc deleted file mode 100644 index bdfaddc6229..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc +++ /dev/null @@ -1,362 +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/hpack/decoder/hpack_entry_type_decoder.h" - -#include "absl/strings/str_cat.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 "http2/platform/api/http2_logging.h" - -namespace http2 { - -std::string HpackEntryTypeDecoder::DebugString() const { - return absl::StrCat( - "HpackEntryTypeDecoder(varint_decoder=", varint_decoder_.DebugString(), - ", entry_type=", entry_type_, ")"); -} - -std::ostream& operator<<(std::ostream& out, const HpackEntryTypeDecoder& v) { - return out << v.DebugString(); -} - -// This ridiculous looking function turned out to be the winner in benchmarking -// of several very different alternative implementations. It would be even -// faster (~7%) if inlined in the header file, but I'm not sure if that is -// worth doing... yet. -// TODO(jamessynge): Benchmark again at a higher level (e.g. at least at the -// full HTTP/2 decoder level, but preferably still higher) to determine if the -// alternatives that take less code/data space are preferable in that situation. -DecodeStatus HpackEntryTypeDecoder::Start(DecodeBuffer* db) { - QUICHE_DCHECK(db != nullptr); - QUICHE_DCHECK(db->HasData()); - - // The high four bits (nibble) of first byte of the entry determine the type - // of the entry, and may also be the initial bits of the varint that - // represents an index or table size. Note the use of the word 'initial' - // rather than 'high'; the HPACK encoding of varints is not in network - // order (i.e. not big-endian, the high-order byte isn't first), nor in - // little-endian order. See: - // http://httpwg.org/specs/rfc7541.html#integer.representation - uint8_t byte = db->DecodeUInt8(); - switch (byte) { - case 0b00000000: - case 0b00000001: - case 0b00000010: - case 0b00000011: - case 0b00000100: - case 0b00000101: - case 0b00000110: - case 0b00000111: - case 0b00001000: - case 0b00001001: - case 0b00001010: - case 0b00001011: - case 0b00001100: - case 0b00001101: - case 0b00001110: - // The low 4 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - entry_type_ = HpackEntryType::kUnindexedLiteralHeader; - varint_decoder_.set_value(byte); - return DecodeStatus::kDecodeDone; - - case 0b00001111: - // The low 4 bits of |byte| are the initial bits of the varint. All 4 - // are 1, so the varint extends into another byte. - entry_type_ = HpackEntryType::kUnindexedLiteralHeader; - return varint_decoder_.StartExtended(4, db); - - case 0b00010000: - case 0b00010001: - case 0b00010010: - case 0b00010011: - case 0b00010100: - case 0b00010101: - case 0b00010110: - case 0b00010111: - case 0b00011000: - case 0b00011001: - case 0b00011010: - case 0b00011011: - case 0b00011100: - case 0b00011101: - case 0b00011110: - // The low 4 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - entry_type_ = HpackEntryType::kNeverIndexedLiteralHeader; - varint_decoder_.set_value(byte & 0x0f); - return DecodeStatus::kDecodeDone; - - case 0b00011111: - // The low 4 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - entry_type_ = HpackEntryType::kNeverIndexedLiteralHeader; - return varint_decoder_.StartExtended(4, db); - - case 0b00100000: - case 0b00100001: - case 0b00100010: - case 0b00100011: - case 0b00100100: - case 0b00100101: - case 0b00100110: - case 0b00100111: - case 0b00101000: - case 0b00101001: - case 0b00101010: - case 0b00101011: - case 0b00101100: - case 0b00101101: - case 0b00101110: - case 0b00101111: - case 0b00110000: - case 0b00110001: - case 0b00110010: - case 0b00110011: - case 0b00110100: - case 0b00110101: - case 0b00110110: - case 0b00110111: - case 0b00111000: - case 0b00111001: - case 0b00111010: - case 0b00111011: - case 0b00111100: - case 0b00111101: - case 0b00111110: - entry_type_ = HpackEntryType::kDynamicTableSizeUpdate; - // The low 5 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - varint_decoder_.set_value(byte & 0x01f); - return DecodeStatus::kDecodeDone; - - case 0b00111111: - entry_type_ = HpackEntryType::kDynamicTableSizeUpdate; - // The low 5 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - return varint_decoder_.StartExtended(5, db); - - case 0b01000000: - case 0b01000001: - case 0b01000010: - case 0b01000011: - case 0b01000100: - case 0b01000101: - case 0b01000110: - case 0b01000111: - case 0b01001000: - case 0b01001001: - case 0b01001010: - case 0b01001011: - case 0b01001100: - case 0b01001101: - case 0b01001110: - case 0b01001111: - case 0b01010000: - case 0b01010001: - case 0b01010010: - case 0b01010011: - case 0b01010100: - case 0b01010101: - case 0b01010110: - case 0b01010111: - case 0b01011000: - case 0b01011001: - case 0b01011010: - case 0b01011011: - case 0b01011100: - case 0b01011101: - case 0b01011110: - case 0b01011111: - case 0b01100000: - case 0b01100001: - case 0b01100010: - case 0b01100011: - case 0b01100100: - case 0b01100101: - case 0b01100110: - case 0b01100111: - case 0b01101000: - case 0b01101001: - case 0b01101010: - case 0b01101011: - case 0b01101100: - case 0b01101101: - case 0b01101110: - case 0b01101111: - case 0b01110000: - case 0b01110001: - case 0b01110010: - case 0b01110011: - case 0b01110100: - case 0b01110101: - case 0b01110110: - case 0b01110111: - case 0b01111000: - case 0b01111001: - case 0b01111010: - case 0b01111011: - case 0b01111100: - case 0b01111101: - case 0b01111110: - entry_type_ = HpackEntryType::kIndexedLiteralHeader; - // The low 6 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - varint_decoder_.set_value(byte & 0x03f); - return DecodeStatus::kDecodeDone; - - case 0b01111111: - entry_type_ = HpackEntryType::kIndexedLiteralHeader; - // The low 6 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - return varint_decoder_.StartExtended(6, db); - - case 0b10000000: - case 0b10000001: - case 0b10000010: - case 0b10000011: - case 0b10000100: - case 0b10000101: - case 0b10000110: - case 0b10000111: - case 0b10001000: - case 0b10001001: - case 0b10001010: - case 0b10001011: - case 0b10001100: - case 0b10001101: - case 0b10001110: - case 0b10001111: - case 0b10010000: - case 0b10010001: - case 0b10010010: - case 0b10010011: - case 0b10010100: - case 0b10010101: - case 0b10010110: - case 0b10010111: - case 0b10011000: - case 0b10011001: - case 0b10011010: - case 0b10011011: - case 0b10011100: - case 0b10011101: - case 0b10011110: - case 0b10011111: - case 0b10100000: - case 0b10100001: - case 0b10100010: - case 0b10100011: - case 0b10100100: - case 0b10100101: - case 0b10100110: - case 0b10100111: - case 0b10101000: - case 0b10101001: - case 0b10101010: - case 0b10101011: - case 0b10101100: - case 0b10101101: - case 0b10101110: - case 0b10101111: - case 0b10110000: - case 0b10110001: - case 0b10110010: - case 0b10110011: - case 0b10110100: - case 0b10110101: - case 0b10110110: - case 0b10110111: - case 0b10111000: - case 0b10111001: - case 0b10111010: - case 0b10111011: - case 0b10111100: - case 0b10111101: - case 0b10111110: - case 0b10111111: - case 0b11000000: - case 0b11000001: - case 0b11000010: - case 0b11000011: - case 0b11000100: - case 0b11000101: - case 0b11000110: - case 0b11000111: - case 0b11001000: - case 0b11001001: - case 0b11001010: - case 0b11001011: - case 0b11001100: - case 0b11001101: - case 0b11001110: - case 0b11001111: - case 0b11010000: - case 0b11010001: - case 0b11010010: - case 0b11010011: - case 0b11010100: - case 0b11010101: - case 0b11010110: - case 0b11010111: - case 0b11011000: - case 0b11011001: - case 0b11011010: - case 0b11011011: - case 0b11011100: - case 0b11011101: - case 0b11011110: - case 0b11011111: - case 0b11100000: - case 0b11100001: - case 0b11100010: - case 0b11100011: - case 0b11100100: - case 0b11100101: - case 0b11100110: - case 0b11100111: - case 0b11101000: - case 0b11101001: - case 0b11101010: - case 0b11101011: - case 0b11101100: - case 0b11101101: - case 0b11101110: - case 0b11101111: - case 0b11110000: - case 0b11110001: - case 0b11110010: - case 0b11110011: - case 0b11110100: - case 0b11110101: - case 0b11110110: - case 0b11110111: - case 0b11111000: - case 0b11111001: - case 0b11111010: - case 0b11111011: - case 0b11111100: - case 0b11111101: - case 0b11111110: - entry_type_ = HpackEntryType::kIndexedHeader; - // The low 7 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - varint_decoder_.set_value(byte & 0x07f); - return DecodeStatus::kDecodeDone; - - case 0b11111111: - entry_type_ = HpackEntryType::kIndexedHeader; - // The low 7 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - return varint_decoder_.StartExtended(7, db); - } - HTTP2_BUG(http2_bug_66_1) - << "Unreachable, byte=" << std::hex << static_cast<uint32_t>(byte); - HTTP2_CODE_COUNT_N(decompress_failure_3, 17, 23); - return DecodeStatus::kDecodeError; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.h deleted file mode 100644 index dac0823791d..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.h +++ /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. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_ - -// Decodes the type of an HPACK entry, and the variable length integer whose -// prefix is in the low-order bits of the same byte, "below" the type bits. -// The integer represents an index into static or dynamic table, which may be -// zero, or is the new size limit of the dynamic table. - -#include <cstdint> -#include <string> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "http2/hpack/varint/hpack_varint_decoder.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE HpackEntryTypeDecoder { - public: - // Only call when the decode buffer has data (i.e. HpackEntryDecoder must - // not call until there is data). - DecodeStatus Start(DecodeBuffer* db); - - // Only call Resume if the previous call (Start or Resume) returned - // DecodeStatus::kDecodeInProgress. - DecodeStatus Resume(DecodeBuffer* db) { return varint_decoder_.Resume(db); } - - // Returns the decoded entry type. Only call if the preceding call to Start - // or Resume returned kDecodeDone. - HpackEntryType entry_type() const { return entry_type_; } - - // Returns the decoded variable length integer. Only call if the - // preceding call to Start or Resume returned kDecodeDone. - uint64_t varint() const { return varint_decoder_.value(); } - - std::string DebugString() const; - - private: - HpackVarintDecoder varint_decoder_; - - // This field is initialized just to keep ASAN happy about reading it - // from DebugString(). - HpackEntryType entry_type_ = HpackEntryType::kIndexedHeader; -}; - -QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackEntryTypeDecoder& v); - -} // namespace http2 -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder_test.cc deleted file mode 100644 index 8babd809e82..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder_test.cc +++ /dev/null @@ -1,85 +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/hpack/decoder/hpack_entry_type_decoder.h" - -#include <vector> - -#include "http2/hpack/tools/hpack_block_builder.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { -const bool kReturnNonZeroOnFirst = true; - -class HpackEntryTypeDecoderTest : public RandomDecoderTest { - protected: - DecodeStatus StartDecoding(DecodeBuffer* b) override { - QUICHE_CHECK_LT(0u, b->Remaining()); - return decoder_.Start(b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b); - } - - HpackEntryTypeDecoder decoder_; -}; - -TEST_F(HpackEntryTypeDecoderTest, DynamicTableSizeUpdate) { - for (uint32_t size = 0; size < 1000 * 1000; size += 256) { - HpackBlockBuilder bb; - bb.AppendDynamicTableSizeUpdate(size); - DecodeBuffer db(bb.buffer()); - auto validator = [size, this]() -> AssertionResult { - VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type()); - VERIFY_EQ(size, decoder_.varint()); - return AssertionSuccess(); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst, - ValidateDoneAndEmpty(validator))) - << "\nentry_type=kDynamicTableSizeUpdate, size=" << size; - // Run the validator again to make sure that DecodeAndValidateSeveralWays - // did the right thing. - EXPECT_TRUE(validator()); - } -} - -TEST_F(HpackEntryTypeDecoderTest, HeaderWithIndex) { - std::vector<HpackEntryType> entry_types = { - HpackEntryType::kIndexedHeader, - HpackEntryType::kIndexedLiteralHeader, - HpackEntryType::kUnindexedLiteralHeader, - HpackEntryType::kNeverIndexedLiteralHeader, - }; - for (const HpackEntryType entry_type : entry_types) { - const uint32_t first = entry_type == HpackEntryType::kIndexedHeader ? 1 : 0; - for (uint32_t index = first; index < 1000; ++index) { - HpackBlockBuilder bb; - bb.AppendEntryTypeAndVarint(entry_type, index); - DecodeBuffer db(bb.buffer()); - auto validator = [entry_type, index, this]() -> AssertionResult { - VERIFY_EQ(entry_type, decoder_.entry_type()); - VERIFY_EQ(index, decoder_.varint()); - return AssertionSuccess(); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst, - ValidateDoneAndEmpty(validator))) - << "\nentry_type=" << entry_type << ", index=" << index; - // Run the validator again to make sure that DecodeAndValidateSeveralWays - // did the right thing. - EXPECT_TRUE(validator()); - } - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc deleted file mode 100644 index eeed643d3ff..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc +++ /dev/null @@ -1,124 +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/hpack/decoder/hpack_string_collector.h" - -#include <stddef.h> - -#include <iosfwd> -#include <ostream> - -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -namespace { - -std::ostream& operator<<(std::ostream& out, - HpackStringCollector::CollectorState v) { - switch (v) { - case HpackStringCollector::CollectorState::kGenesis: - return out << "kGenesis"; - case HpackStringCollector::CollectorState::kStarted: - return out << "kStarted"; - case HpackStringCollector::CollectorState::kEnded: - return out << "kEnded"; - } - return out << "UnknownCollectorState"; -} - -} // namespace - -HpackStringCollector::HpackStringCollector() { - Clear(); -} - -HpackStringCollector::HpackStringCollector(const std::string& str, bool huffman) - : s(str), len(str.size()), huffman_encoded(huffman), state(kEnded) {} - -void HpackStringCollector::Clear() { - s = ""; - len = 0; - huffman_encoded = false; - state = kGenesis; -} - -bool HpackStringCollector::IsClear() const { - return s.empty() && len == 0 && huffman_encoded == false && state == kGenesis; -} - -bool HpackStringCollector::IsInProgress() const { - return state == kStarted; -} - -bool HpackStringCollector::HasEnded() const { - return state == kEnded; -} - -void HpackStringCollector::OnStringStart(bool huffman, size_t length) { - EXPECT_TRUE(IsClear()) << ToString(); - state = kStarted; - huffman_encoded = huffman; - len = length; -} - -void HpackStringCollector::OnStringData(const char* data, size_t length) { - absl::string_view sp(data, length); - EXPECT_TRUE(IsInProgress()) << ToString(); - EXPECT_LE(sp.size(), len) << ToString(); - absl::StrAppend(&s, sp); - EXPECT_LE(s.size(), len) << ToString(); -} - -void HpackStringCollector::OnStringEnd() { - EXPECT_TRUE(IsInProgress()) << ToString(); - EXPECT_EQ(s.size(), len) << ToString(); - state = kEnded; -} - -::testing::AssertionResult HpackStringCollector::Collected( - absl::string_view str, - bool is_huffman_encoded) const { - VERIFY_TRUE(HasEnded()); - VERIFY_EQ(str.size(), len); - VERIFY_EQ(is_huffman_encoded, huffman_encoded); - VERIFY_EQ(str, s); - return ::testing::AssertionSuccess(); -} - -std::string HpackStringCollector::ToString() const { - std::stringstream ss; - ss << *this; - return ss.str(); -} - -bool operator==(const HpackStringCollector& a, const HpackStringCollector& b) { - return a.s == b.s && a.len == b.len && - a.huffman_encoded == b.huffman_encoded && a.state == b.state; -} - -bool operator!=(const HpackStringCollector& a, const HpackStringCollector& b) { - return !(a == b); -} - -std::ostream& operator<<(std::ostream& out, const HpackStringCollector& v) { - out << "HpackStringCollector(state=" << v.state; - if (v.state == HpackStringCollector::kGenesis) { - return out << ")"; - } - if (v.huffman_encoded) { - out << ", Huffman Encoded"; - } - out << ", Length=" << v.len; - if (!v.s.empty() && v.len != v.s.size()) { - out << " (" << v.s.size() << ")"; - } - return out << ", String=\"" << absl::CHexEscape(v.s) << "\")"; -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.h deleted file mode 100644 index 3ec6560b27b..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.h +++ /dev/null @@ -1,63 +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_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_ - -// Supports tests of decoding HPACK strings. - -#include <stddef.h> - -#include <iosfwd> -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/hpack/decoder/hpack_string_decoder_listener.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -// Records the callbacks associated with a decoding a string; must -// call Clear() between decoding successive strings. -struct HpackStringCollector : public HpackStringDecoderListener { - enum CollectorState { - kGenesis, - kStarted, - kEnded, - }; - - HpackStringCollector(); - HpackStringCollector(const std::string& str, bool huffman); - - void Clear(); - bool IsClear() const; - bool IsInProgress() const; - bool HasEnded() const; - - void OnStringStart(bool huffman, size_t length) override; - void OnStringData(const char* data, size_t length) override; - void OnStringEnd() override; - - ::testing::AssertionResult Collected(absl::string_view str, - bool is_huffman_encoded) const; - - std::string ToString() const; - - std::string s; - size_t len; - bool huffman_encoded; - CollectorState state; -}; - -bool operator==(const HpackStringCollector& a, const HpackStringCollector& b); - -bool operator!=(const HpackStringCollector& a, const HpackStringCollector& b); - -std::ostream& operator<<(std::ostream& out, const HpackStringCollector& v); - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.cc deleted file mode 100644 index 90da300c4a1..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.cc +++ /dev/null @@ -1,35 +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/hpack/decoder/hpack_string_decoder.h" - -#include "absl/strings/str_cat.h" - -namespace http2 { - -std::string HpackStringDecoder::DebugString() const { - return absl::StrCat("HpackStringDecoder(state=", StateToString(state_), - ", length=", length_decoder_.DebugString(), - ", remaining=", remaining_, - ", huffman=", huffman_encoded_ ? "true)" : "false)"); -} - -// static -std::string HpackStringDecoder::StateToString(StringDecoderState v) { - switch (v) { - case kStartDecodingLength: - return "kStartDecodingLength"; - case kDecodingString: - return "kDecodingString"; - case kResumeDecodingLength: - return "kResumeDecodingLength"; - } - return absl::StrCat("UNKNOWN_STATE(", static_cast<uint32_t>(v), ")"); -} - -std::ostream& operator<<(std::ostream& out, const HpackStringDecoder& v) { - return out << v.DebugString(); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.h deleted file mode 100644 index 9cddc67f9b4..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.h +++ /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. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_ - -// HpackStringDecoder decodes strings encoded per the HPACK spec; this does -// not mean decompressing Huffman encoded strings, just identifying the length, -// encoding and contents for a listener. - -#include <stddef.h> - -#include <algorithm> -#include <cstdint> -#include <string> - -#include "absl/base/macros.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/hpack/varint/hpack_varint_decoder.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -// Decodes a single string in an HPACK header entry. The high order bit of -// the first byte of the length is the H (Huffman) bit indicating whether -// the value is Huffman encoded, and the remainder of the byte is the first -// 7 bits of an HPACK varint. -// -// Call Start() to begin decoding; if it returns kDecodeInProgress, then call -// Resume() when more input is available, repeating until kDecodeInProgress is -// not returned. If kDecodeDone or kDecodeError is returned, then Resume() must -// not be called until Start() has been called to start decoding a new string. -class QUICHE_EXPORT_PRIVATE HpackStringDecoder { - public: - enum StringDecoderState { - kStartDecodingLength, - kDecodingString, - kResumeDecodingLength, - }; - - template <class Listener> - DecodeStatus Start(DecodeBuffer* db, Listener* cb) { - // Fast decode path is used if the string is under 127 bytes and the - // entire length of the string is in the decode buffer. More than 83% of - // string lengths are encoded in just one byte. - if (db->HasData() && (*db->cursor() & 0x7f) != 0x7f) { - // The string is short. - uint8_t h_and_prefix = db->DecodeUInt8(); - uint8_t length = h_and_prefix & 0x7f; - bool huffman_encoded = (h_and_prefix & 0x80) == 0x80; - cb->OnStringStart(huffman_encoded, length); - if (length <= db->Remaining()) { - // Yeah, we've got the whole thing in the decode buffer. - // Ideally this will be the common case. Note that we don't - // update any of the member variables in this path. - cb->OnStringData(db->cursor(), length); - db->AdvanceCursor(length); - cb->OnStringEnd(); - return DecodeStatus::kDecodeDone; - } - // Not all in the buffer. - huffman_encoded_ = huffman_encoded; - remaining_ = length; - // Call Resume to decode the string body, which is only partially - // in the decode buffer (or not at all). - state_ = kDecodingString; - return Resume(db, cb); - } - // Call Resume to decode the string length, which is either not in - // the decode buffer, or spans multiple bytes. - state_ = kStartDecodingLength; - return Resume(db, cb); - } - - template <class Listener> - DecodeStatus Resume(DecodeBuffer* db, Listener* cb) { - DecodeStatus status; - while (true) { - switch (state_) { - case kStartDecodingLength: - HTTP2_DVLOG(2) << "kStartDecodingLength: db->Remaining=" - << db->Remaining(); - if (!StartDecodingLength(db, cb, &status)) { - // The length is split across decode buffers. - return status; - } - // We've finished decoding the length, which spanned one or more - // bytes. Approximately 17% of strings have a length that is greater - // than 126 bytes, and thus the length is encoded in more than one - // byte, and so doesn't get the benefit of the optimization in - // Start() for single byte lengths. But, we still expect that most - // of such strings will be contained entirely in a single decode - // buffer, and hence this fall through skips another trip through the - // switch above and more importantly skips setting the state_ variable - // again in those cases where we don't need it. - ABSL_FALLTHROUGH_INTENDED; - - case kDecodingString: - HTTP2_DVLOG(2) << "kDecodingString: db->Remaining=" << db->Remaining() - << " remaining_=" << remaining_; - return DecodeString(db, cb); - - case kResumeDecodingLength: - HTTP2_DVLOG(2) << "kResumeDecodingLength: db->Remaining=" - << db->Remaining(); - if (!ResumeDecodingLength(db, cb, &status)) { - return status; - } - } - } - } - - std::string DebugString() const; - - private: - static std::string StateToString(StringDecoderState v); - - // Returns true if the length is fully decoded and the listener wants the - // decoding to continue, false otherwise; status is set to the status from - // the varint decoder. - // If the length is not fully decoded, case state_ is set appropriately - // for the next call to Resume. - template <class Listener> - bool StartDecodingLength(DecodeBuffer* db, - Listener* cb, - DecodeStatus* status) { - if (db->Empty()) { - *status = DecodeStatus::kDecodeInProgress; - state_ = kStartDecodingLength; - return false; - } - uint8_t h_and_prefix = db->DecodeUInt8(); - huffman_encoded_ = (h_and_prefix & 0x80) == 0x80; - *status = length_decoder_.Start(h_and_prefix, 7, db); - if (*status == DecodeStatus::kDecodeDone) { - OnStringStart(cb, status); - return true; - } - // Set the state to cover the DecodeStatus::kDecodeInProgress case. - // Won't be needed if the status is kDecodeError. - state_ = kResumeDecodingLength; - return false; - } - - // Returns true if the length is fully decoded and the listener wants the - // decoding to continue, false otherwise; status is set to the status from - // the varint decoder; state_ is updated when fully decoded. - // If the length is not fully decoded, case state_ is set appropriately - // for the next call to Resume. - template <class Listener> - bool ResumeDecodingLength(DecodeBuffer* db, - Listener* cb, - DecodeStatus* status) { - QUICHE_DCHECK_EQ(state_, kResumeDecodingLength); - *status = length_decoder_.Resume(db); - if (*status == DecodeStatus::kDecodeDone) { - state_ = kDecodingString; - OnStringStart(cb, status); - return true; - } - return false; - } - - // Returns true if the listener wants the decoding to continue, and - // false otherwise, in which case status set. - template <class Listener> - void OnStringStart(Listener* cb, DecodeStatus* /*status*/) { - // TODO(vasilvv): fail explicitly in case of truncation. - remaining_ = static_cast<size_t>(length_decoder_.value()); - // Make callback so consumer knows what is coming. - cb->OnStringStart(huffman_encoded_, remaining_); - } - - // Passes the available portion of the string to the listener, and signals - // the end of the string when it is reached. Returns kDecodeDone or - // kDecodeInProgress as appropriate. - template <class Listener> - DecodeStatus DecodeString(DecodeBuffer* db, Listener* cb) { - size_t len = std::min(remaining_, db->Remaining()); - if (len > 0) { - cb->OnStringData(db->cursor(), len); - db->AdvanceCursor(len); - remaining_ -= len; - } - if (remaining_ == 0) { - cb->OnStringEnd(); - return DecodeStatus::kDecodeDone; - } - state_ = kDecodingString; - return DecodeStatus::kDecodeInProgress; - } - - HpackVarintDecoder length_decoder_; - - // These fields are initialized just to keep ASAN happy about reading - // them from DebugString(). - size_t remaining_ = 0; - StringDecoderState state_ = kStartDecodingLength; - bool huffman_encoded_ = false; -}; - -QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackStringDecoder& v); - -} // namespace http2 -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.cc deleted file mode 100644 index 73db24fe407..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.cc +++ /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. - -#include "http2/hpack/decoder/hpack_string_decoder_listener.h" - -#include "http2/platform/api/http2_logging.h" - -namespace http2 { -namespace test { - -void HpackStringDecoderVLoggingListener::OnStringStart(bool huffman_encoded, - size_t len) { - HTTP2_VLOG(1) << "OnStringStart: H=" << huffman_encoded << ", len=" << len; - if (wrapped_) { - wrapped_->OnStringStart(huffman_encoded, len); - } -} - -void HpackStringDecoderVLoggingListener::OnStringData(const char* data, - size_t len) { - HTTP2_VLOG(1) << "OnStringData: len=" << len; - if (wrapped_) { - return wrapped_->OnStringData(data, len); - } -} - -void HpackStringDecoderVLoggingListener::OnStringEnd() { - HTTP2_VLOG(1) << "OnStringEnd"; - if (wrapped_) { - return wrapped_->OnStringEnd(); - } -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.h deleted file mode 100644 index 25b7eeac9f9..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.h +++ /dev/null @@ -1,62 +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_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_ - -// Defines HpackStringDecoderListener which defines the methods required by an -// HpackStringDecoder. Also defines HpackStringDecoderVLoggingListener which -// logs before calling another HpackStringDecoderListener implementation. -// For now these are only used by tests, so placed in the test namespace. - -#include <stddef.h> - -#include "common/platform/api/quiche_export.h" - -namespace http2 { -namespace test { - -// HpackStringDecoder methods require a listener that implements the methods -// below, but it is NOT necessary to extend this class because the methods -// are templates. -class QUICHE_EXPORT_PRIVATE HpackStringDecoderListener { - public: - virtual ~HpackStringDecoderListener() {} - - // Called at the start of decoding an HPACK string. The encoded length of the - // string is |len| bytes, which may be zero. The string is Huffman encoded - // if huffman_encoded is true, else it is plain text (i.e. the encoded length - // is then the plain text length). - virtual void OnStringStart(bool huffman_encoded, size_t len) = 0; - - // Called when some data is available, or once when the string length is zero - // (to simplify the decoder, it doesn't have a special case for len==0). - virtual void OnStringData(const char* data, size_t len) = 0; - - // Called after OnStringData has provided all of the encoded bytes of the - // string. - virtual void OnStringEnd() = 0; -}; - -class QUICHE_EXPORT_PRIVATE HpackStringDecoderVLoggingListener - : public HpackStringDecoderListener { - public: - HpackStringDecoderVLoggingListener() : wrapped_(nullptr) {} - explicit HpackStringDecoderVLoggingListener( - HpackStringDecoderListener* wrapped) - : wrapped_(wrapped) {} - ~HpackStringDecoderVLoggingListener() override {} - - void OnStringStart(bool huffman_encoded, size_t len) override; - void OnStringData(const char* data, size_t len) override; - void OnStringEnd() override; - - private: - HpackStringDecoderListener* const wrapped_; -}; - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_test.cc deleted file mode 100644 index 6ff332f92a6..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_test.cc +++ /dev/null @@ -1,154 +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/hpack/decoder/hpack_string_decoder.h" - -// Tests of HpackStringDecoder. - -#include "absl/strings/string_view.h" -#include "http2/hpack/decoder/hpack_string_collector.h" -#include "http2/hpack/decoder/hpack_string_decoder_listener.h" -#include "http2/hpack/tools/hpack_block_builder.h" -#include "http2/platform/api/http2_test_helpers.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 { - -const bool kMayReturnZeroOnFirst = false; -const bool kCompressed = true; -const bool kUncompressed = false; - -class HpackStringDecoderTest : public RandomDecoderTest { - protected: - HpackStringDecoderTest() : listener_(&collector_) {} - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - ++start_decoding_calls_; - collector_.Clear(); - return decoder_.Start(b, &listener_); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - // Provides coverage of DebugString and StateToString. - // Not validating output. - HTTP2_VLOG(1) << decoder_.DebugString(); - HTTP2_VLOG(2) << collector_; - return decoder_.Resume(b, &listener_); - } - - AssertionResult Collected(absl::string_view s, bool huffman_encoded) { - HTTP2_VLOG(1) << collector_; - return collector_.Collected(s, huffman_encoded); - } - - // expected_str is a std::string rather than a const std::string& or - // absl::string_view so that the lambda makes a copy of the string, and thus - // the string to be passed to Collected outlives the call to MakeValidator. - Validator MakeValidator(const std::string& expected_str, - bool expected_huffman) { - return - [expected_str, expected_huffman, this]( - const DecodeBuffer& /*input*/, - DecodeStatus /*status*/) -> AssertionResult { - AssertionResult result = Collected(expected_str, expected_huffman); - if (result) { - VERIFY_EQ(collector_, - HpackStringCollector(expected_str, expected_huffman)); - } else { - VERIFY_NE(collector_, - HpackStringCollector(expected_str, expected_huffman)); - } - HTTP2_VLOG(2) << collector_.ToString(); - collector_.Clear(); - HTTP2_VLOG(2) << collector_; - return result; - }; - } - - HpackStringDecoder decoder_; - HpackStringCollector collector_; - HpackStringDecoderVLoggingListener listener_; - size_t start_decoding_calls_ = 0; -}; - -TEST_F(HpackStringDecoderTest, DecodeEmptyString) { - { - Validator validator = ValidateDoneAndEmpty(MakeValidator("", kCompressed)); - const char kData[] = {'\x80'}; - DecodeBuffer b(kData); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - } - { - // Make sure it stops after decoding the empty string. - Validator validator = - ValidateDoneAndOffset(1, MakeValidator("", kUncompressed)); - const char kData[] = {'\x00', '\xff'}; - DecodeBuffer b(kData); - EXPECT_EQ(2u, b.Remaining()); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - EXPECT_EQ(1u, b.Remaining()); - } -} - -TEST_F(HpackStringDecoderTest, DecodeShortString) { - { - // Make sure it stops after decoding the non-empty string. - Validator validator = - ValidateDoneAndOffset(11, MakeValidator("start end.", kCompressed)); - const char kData[] = "\x8astart end.Don't peek at this."; - DecodeBuffer b(kData); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - } - { - Validator validator = - ValidateDoneAndOffset(11, MakeValidator("start end.", kUncompressed)); - absl::string_view data("\x0astart end."); - DecodeBuffer b(data); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - } -} - -TEST_F(HpackStringDecoderTest, DecodeLongStrings) { - std::string name = Random().RandString(1024); - std::string value = Random().RandString(65536); - HpackBlockBuilder hbb; - - hbb.AppendString(false, name); - uint32_t offset_after_name = hbb.size(); - EXPECT_EQ(3 + name.size(), offset_after_name); - - hbb.AppendString(true, value); - uint32_t offset_after_value = hbb.size(); - EXPECT_EQ(3 + name.size() + 4 + value.size(), offset_after_value); - - DecodeBuffer b(hbb.buffer()); - - // Decode the name... - EXPECT_TRUE(DecodeAndValidateSeveralWays( - &b, kMayReturnZeroOnFirst, - ValidateDoneAndOffset(offset_after_name, - MakeValidator(name, kUncompressed)))); - EXPECT_EQ(offset_after_name, b.Offset()); - EXPECT_EQ(offset_after_value - offset_after_name, b.Remaining()); - - // Decode the value... - EXPECT_TRUE(DecodeAndValidateSeveralWays( - &b, kMayReturnZeroOnFirst, - ValidateDoneAndOffset(offset_after_value - offset_after_name, - MakeValidator(value, kCompressed)))); - EXPECT_EQ(offset_after_value, b.Offset()); - EXPECT_EQ(0u, b.Remaining()); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc deleted file mode 100644 index 1752ba524a2..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc +++ /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. - -#include "http2/hpack/decoder/hpack_whole_entry_buffer.h" - -#include "absl/strings/str_cat.h" -#include "http2/platform/api/http2_flag_utils.h" -#include "http2/platform/api/http2_flags.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_logging.h" -#include "common/quiche_text_utils.h" - -namespace http2 { - -HpackWholeEntryBuffer::HpackWholeEntryBuffer(HpackWholeEntryListener* listener, - size_t max_string_size_bytes) - : max_string_size_bytes_(max_string_size_bytes) { - set_listener(listener); -} -HpackWholeEntryBuffer::~HpackWholeEntryBuffer() = default; - -void HpackWholeEntryBuffer::set_listener(HpackWholeEntryListener* listener) { - QUICHE_CHECK(listener); - listener_ = listener; -} - -void HpackWholeEntryBuffer::set_max_string_size_bytes( - size_t max_string_size_bytes) { - max_string_size_bytes_ = max_string_size_bytes; -} - -void HpackWholeEntryBuffer::BufferStringsIfUnbuffered() { - name_.BufferStringIfUnbuffered(); - value_.BufferStringIfUnbuffered(); -} - -void HpackWholeEntryBuffer::OnIndexedHeader(size_t index) { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnIndexedHeader: index=" << index; - listener_->OnIndexedHeader(index); -} - -void HpackWholeEntryBuffer::OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnStartLiteralHeader: entry_type=" - << entry_type << ", maybe_name_index=" << maybe_name_index; - entry_type_ = entry_type; - maybe_name_index_ = maybe_name_index; -} - -void HpackWholeEntryBuffer::OnNameStart(bool huffman_encoded, size_t len) { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnNameStart: huffman_encoded=" - << (huffman_encoded ? "true" : "false") << ", len=" << len; - QUICHE_DCHECK_EQ(maybe_name_index_, 0u); - if (!error_detected_) { - if (len > max_string_size_bytes_) { - HTTP2_DVLOG(1) << "Name length (" << len << ") is longer than permitted (" - << max_string_size_bytes_ << ")"; - ReportError(HpackDecodingError::kNameTooLong, ""); - HTTP2_CODE_COUNT_N(decompress_failure_3, 18, 23); - return; - } - name_.OnStart(huffman_encoded, len); - } -} - -void HpackWholeEntryBuffer::OnNameData(const char* data, size_t len) { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnNameData: len=" << len - << " data:\n" - << quiche::QuicheTextUtils::HexDump( - absl::string_view(data, len)); - QUICHE_DCHECK_EQ(maybe_name_index_, 0u); - if (!error_detected_ && !name_.OnData(data, len)) { - ReportError(HpackDecodingError::kNameHuffmanError, ""); - HTTP2_CODE_COUNT_N(decompress_failure_3, 19, 23); - } -} - -void HpackWholeEntryBuffer::OnNameEnd() { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnNameEnd"; - QUICHE_DCHECK_EQ(maybe_name_index_, 0u); - if (!error_detected_ && !name_.OnEnd()) { - ReportError(HpackDecodingError::kNameHuffmanError, ""); - HTTP2_CODE_COUNT_N(decompress_failure_3, 20, 23); - } -} - -void HpackWholeEntryBuffer::OnValueStart(bool huffman_encoded, size_t len) { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnValueStart: huffman_encoded=" - << (huffman_encoded ? "true" : "false") << ", len=" << len; - if (!error_detected_) { - if (len > max_string_size_bytes_) { - std::string detailed_error = absl::StrCat( - "Value length (", len, ") of [", name_.GetStringIfComplete(), - "] is longer than permitted (", max_string_size_bytes_, ")"); - HTTP2_DVLOG(1) << detailed_error; - ReportError(HpackDecodingError::kValueTooLong, detailed_error); - HTTP2_CODE_COUNT_N(decompress_failure_3, 21, 23); - return; - } - value_.OnStart(huffman_encoded, len); - } -} - -void HpackWholeEntryBuffer::OnValueData(const char* data, size_t len) { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnValueData: len=" << len - << " data:\n" - << quiche::QuicheTextUtils::HexDump( - absl::string_view(data, len)); - if (!error_detected_ && !value_.OnData(data, len)) { - ReportError(HpackDecodingError::kValueHuffmanError, ""); - HTTP2_CODE_COUNT_N(decompress_failure_3, 22, 23); - } -} - -void HpackWholeEntryBuffer::OnValueEnd() { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnValueEnd"; - if (error_detected_) { - return; - } - if (!value_.OnEnd()) { - ReportError(HpackDecodingError::kValueHuffmanError, ""); - HTTP2_CODE_COUNT_N(decompress_failure_3, 23, 23); - return; - } - if (maybe_name_index_ == 0) { - listener_->OnLiteralNameAndValue(entry_type_, &name_, &value_); - name_.Reset(); - } else { - listener_->OnNameIndexAndLiteralValue(entry_type_, maybe_name_index_, - &value_); - } - value_.Reset(); -} - -void HpackWholeEntryBuffer::OnDynamicTableSizeUpdate(size_t size) { - HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnDynamicTableSizeUpdate: size=" - << size; - listener_->OnDynamicTableSizeUpdate(size); -} - -void HpackWholeEntryBuffer::ReportError(HpackDecodingError error, - std::string detailed_error) { - if (!error_detected_) { - HTTP2_DVLOG(1) << "HpackWholeEntryBuffer::ReportError: " - << HpackDecodingErrorToString(error); - error_detected_ = true; - listener_->OnHpackDecodeError(error, detailed_error); - listener_ = HpackWholeEntryNoOpListener::NoOpListener(); - } -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h deleted file mode 100644 index 0cce0bafd72..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h +++ /dev/null @@ -1,102 +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_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_ - -// HpackWholeEntryBuffer isolates a listener from the fact that an entry may -// be split across multiple input buffers, providing one callback per entry. -// HpackWholeEntryBuffer requires that the HpackEntryDecoderListener be made in -// the correct order, which is tested by hpack_entry_decoder_test.cc. - -#include <stddef.h> - -#include "absl/strings/string_view.h" -#include "http2/hpack/decoder/hpack_decoder_string_buffer.h" -#include "http2/hpack/decoder/hpack_decoding_error.h" -#include "http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "http2/hpack/decoder/hpack_whole_entry_listener.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -// TODO(jamessynge): Consider renaming HpackEntryDecoderListener to -// HpackEntryPartsListener or HpackEntryFragmentsListener. -class QUICHE_EXPORT_PRIVATE HpackWholeEntryBuffer - : public HpackEntryDecoderListener { - public: - // max_string_size specifies the maximum size of an on-the-wire string (name - // or value, plain or Huffman encoded) that will be accepted. See sections - // 5.1 and 5.2 of RFC 7541. This is a defense against OOM attacks; HTTP/2 - // allows a decoder to enforce any limit of the size of the header lists - // that it is willing decode, including less than the MAX_HEADER_LIST_SIZE - // setting, a setting that is initially unlimited. For example, we might - // choose to send a MAX_HEADER_LIST_SIZE of 64KB, and to use that same value - // as the upper bound for individual strings. - HpackWholeEntryBuffer(HpackWholeEntryListener* listener, - size_t max_string_size); - ~HpackWholeEntryBuffer() override; - - HpackWholeEntryBuffer(const HpackWholeEntryBuffer&) = delete; - HpackWholeEntryBuffer& operator=(const HpackWholeEntryBuffer&) = delete; - - // Set the listener to be notified when a whole entry has been decoded. - // The listener may be changed at any time. - void set_listener(HpackWholeEntryListener* listener); - - // Set how much encoded data this decoder is willing to buffer. - // TODO(jamessynge): Come up with consistent semantics for this protection - // across the various decoders; e.g. should it be for a single string or - // a single header entry? - void set_max_string_size_bytes(size_t max_string_size_bytes); - - // Ensure that decoded strings pointed to by the HpackDecoderStringBuffer - // instances name_ and value_ are buffered, which allows any underlying - // transport buffer to be freed or reused without overwriting the decoded - // strings. This is needed only when an HPACK entry is split across transport - // buffers. See HpackDecoder::DecodeFragment. - void BufferStringsIfUnbuffered(); - - // Was an error detected? After an error has been detected and reported, - // no further callbacks will be made to the listener. - bool error_detected() const { return error_detected_; } - - // Implement the HpackEntryDecoderListener methods. - - void OnIndexedHeader(size_t index) override; - void OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - void OnDynamicTableSizeUpdate(size_t size) override; - - private: - void ReportError(HpackDecodingError error, std::string detailed_error); - - HpackWholeEntryListener* listener_; - HpackDecoderStringBuffer name_, value_; - - // max_string_size_bytes_ specifies the maximum allowed size of an on-the-wire - // string. Larger strings will be reported as errors to the listener; the - // endpoint should treat these as COMPRESSION errors, which are CONNECTION - // level errors. - size_t max_string_size_bytes_; - - // The name index (or zero) of the current header entry with a literal value. - size_t maybe_name_index_; - - // The type of the current header entry (with literals) that is being decoded. - HpackEntryType entry_type_; - - bool error_detected_ = false; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc deleted file mode 100644 index 6f41481a6f9..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc +++ /dev/null @@ -1,232 +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/hpack/decoder/hpack_whole_entry_buffer.h" - -// Tests of HpackWholeEntryBuffer: does it buffer correctly, and does it -// detect Huffman decoding errors and oversize string errors? - -#include "http2/platform/api/http2_test_helpers.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::_; -using ::testing::AllOf; -using ::testing::InSequence; -using ::testing::Property; -using ::testing::StrictMock; - -namespace http2 { -namespace test { -namespace { - -constexpr size_t kMaxStringSize = 20; - -class MockHpackWholeEntryListener : public HpackWholeEntryListener { - public: - ~MockHpackWholeEntryListener() override = default; - - MOCK_METHOD(void, OnIndexedHeader, (size_t index), (override)); - MOCK_METHOD(void, - OnNameIndexAndLiteralValue, - (HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer), - (override)); - MOCK_METHOD(void, - OnLiteralNameAndValue, - (HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer), - (override)); - MOCK_METHOD(void, OnDynamicTableSizeUpdate, (size_t size), (override)); - MOCK_METHOD(void, - OnHpackDecodeError, - (HpackDecodingError error, std::string detailed_error), - (override)); -}; - -class HpackWholeEntryBufferTest : public QuicheTest { - protected: - HpackWholeEntryBufferTest() : entry_buffer_(&listener_, kMaxStringSize) {} - ~HpackWholeEntryBufferTest() override = default; - - StrictMock<MockHpackWholeEntryListener> listener_; - HpackWholeEntryBuffer entry_buffer_; -}; - -// OnIndexedHeader is an immediate pass through. -TEST_F(HpackWholeEntryBufferTest, OnIndexedHeader) { - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(17)); - entry_buffer_.OnIndexedHeader(17); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(62)); - entry_buffer_.OnIndexedHeader(62); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(62)); - entry_buffer_.OnIndexedHeader(62); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(128)); - entry_buffer_.OnIndexedHeader(128); - } - StrictMock<MockHpackWholeEntryListener> listener2; - entry_buffer_.set_listener(&listener2); - { - InSequence seq; - EXPECT_CALL(listener2, OnIndexedHeader(100)); - entry_buffer_.OnIndexedHeader(100); - } -} - -// OnDynamicTableSizeUpdate is an immediate pass through. -TEST_F(HpackWholeEntryBufferTest, OnDynamicTableSizeUpdate) { - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(4096)); - entry_buffer_.OnDynamicTableSizeUpdate(4096); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(0)); - entry_buffer_.OnDynamicTableSizeUpdate(0); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(1024)); - entry_buffer_.OnDynamicTableSizeUpdate(1024); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(1024)); - entry_buffer_.OnDynamicTableSizeUpdate(1024); - } - StrictMock<MockHpackWholeEntryListener> listener2; - entry_buffer_.set_listener(&listener2); - { - InSequence seq; - EXPECT_CALL(listener2, OnDynamicTableSizeUpdate(0)); - entry_buffer_.OnDynamicTableSizeUpdate(0); - } -} - -TEST_F(HpackWholeEntryBufferTest, OnNameIndexAndLiteralValue) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kNeverIndexedLiteralHeader, - 123); - entry_buffer_.OnValueStart(false, 10); - entry_buffer_.OnValueData("some data.", 10); - - // Force the value to be buffered. - entry_buffer_.BufferStringsIfUnbuffered(); - - EXPECT_CALL( - listener_, - OnNameIndexAndLiteralValue( - HpackEntryType::kNeverIndexedLiteralHeader, 123, - AllOf(Property(&HpackDecoderStringBuffer::str, "some data."), - Property(&HpackDecoderStringBuffer::BufferedLength, 10)))); - - entry_buffer_.OnValueEnd(); -} - -TEST_F(HpackWholeEntryBufferTest, OnLiteralNameAndValue) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0); - // Force the name to be buffered by delivering it in two pieces. - entry_buffer_.OnNameStart(false, 9); - entry_buffer_.OnNameData("some-", 5); - entry_buffer_.OnNameData("name", 4); - entry_buffer_.OnNameEnd(); - entry_buffer_.OnValueStart(false, 12); - entry_buffer_.OnValueData("Header Value", 12); - - EXPECT_CALL( - listener_, - OnLiteralNameAndValue( - HpackEntryType::kIndexedLiteralHeader, - AllOf(Property(&HpackDecoderStringBuffer::str, "some-name"), - Property(&HpackDecoderStringBuffer::BufferedLength, 9)), - AllOf(Property(&HpackDecoderStringBuffer::str, "Header Value"), - Property(&HpackDecoderStringBuffer::BufferedLength, 0)))); - - entry_buffer_.OnValueEnd(); -} - -// Verify that a name longer than the allowed size generates an error. -TEST_F(HpackWholeEntryBufferTest, NameTooLong) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0); - EXPECT_CALL(listener_, - OnHpackDecodeError(HpackDecodingError::kNameTooLong, _)); - entry_buffer_.OnNameStart(false, kMaxStringSize + 1); -} - -// Verify that a value longer than the allowed size generates an error. -TEST_F(HpackWholeEntryBufferTest, ValueTooLong) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0); - EXPECT_CALL(listener_, - OnHpackDecodeError( - HpackDecodingError::kValueTooLong, - "Value length (21) of [path] is longer than permitted (20)")); - entry_buffer_.OnNameStart(false, 4); - entry_buffer_.OnNameData("path", 4); - entry_buffer_.OnNameEnd(); - entry_buffer_.OnValueStart(false, kMaxStringSize + 1); -} - -// Regression test for b/162141899. -TEST_F(HpackWholeEntryBufferTest, ValueTooLongWithoutName) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 1); - EXPECT_CALL(listener_, - OnHpackDecodeError( - HpackDecodingError::kValueTooLong, - "Value length (21) of [] is longer than permitted (20)")); - entry_buffer_.OnValueStart(false, kMaxStringSize + 1); -} - -// Verify that a Huffman encoded name with an explicit EOS generates an error -// for an explicit EOS. -TEST_F(HpackWholeEntryBufferTest, NameHuffmanError) { - const char data[] = "\xff\xff\xff"; - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kUnindexedLiteralHeader, - 0); - entry_buffer_.OnNameStart(true, 4); - entry_buffer_.OnNameData(data, 3); - - EXPECT_CALL(listener_, - OnHpackDecodeError(HpackDecodingError::kNameHuffmanError, _)); - - entry_buffer_.OnNameData(data, 1); - - // After an error is reported, the listener is not called again. - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(8096)).Times(0); - entry_buffer_.OnDynamicTableSizeUpdate(8096); -} - -// Verify that a Huffman encoded value that isn't properly terminated with -// a partial EOS symbol generates an error. -TEST_F(HpackWholeEntryBufferTest, ValueHuffmanError) { - const char data[] = "\x00\x00\x00"; - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kNeverIndexedLiteralHeader, - 61); - entry_buffer_.OnValueStart(true, 3); - entry_buffer_.OnValueData(data, 3); - - EXPECT_CALL(listener_, - OnHpackDecodeError(HpackDecodingError::kValueHuffmanError, _)); - - entry_buffer_.OnValueEnd(); - - // After an error is reported, the listener is not called again. - EXPECT_CALL(listener_, OnIndexedHeader(17)).Times(0); - entry_buffer_.OnIndexedHeader(17); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.cc deleted file mode 100644 index 5ef9c4f3298..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.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/hpack/decoder/hpack_whole_entry_listener.h" - -namespace http2 { - -HpackWholeEntryListener::~HpackWholeEntryListener() = default; - -HpackWholeEntryNoOpListener::~HpackWholeEntryNoOpListener() = default; - -void HpackWholeEntryNoOpListener::OnIndexedHeader(size_t /*index*/) {} -void HpackWholeEntryNoOpListener::OnNameIndexAndLiteralValue( - HpackEntryType /*entry_type*/, - size_t /*name_index*/, - HpackDecoderStringBuffer* /*value_buffer*/) {} -void HpackWholeEntryNoOpListener::OnLiteralNameAndValue( - HpackEntryType /*entry_type*/, - HpackDecoderStringBuffer* /*name_buffer*/, - HpackDecoderStringBuffer* /*value_buffer*/) {} -void HpackWholeEntryNoOpListener::OnDynamicTableSizeUpdate(size_t /*size*/) {} -void HpackWholeEntryNoOpListener::OnHpackDecodeError( - HpackDecodingError /*error*/, - std::string /*detailed_error*/) {} - -// static -HpackWholeEntryNoOpListener* HpackWholeEntryNoOpListener::NoOpListener() { - static HpackWholeEntryNoOpListener* static_instance = - new HpackWholeEntryNoOpListener(); - return static_instance; -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.h deleted file mode 100644 index 3593af36923..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.h +++ /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. - -// Defines HpackWholeEntryListener, the base class of listeners for decoded -// complete HPACK entries, as opposed to HpackEntryDecoderListener which -// receives multiple callbacks for some single entries. - -#ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_ -#define QUICHE_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_ - -#include <stddef.h> - -#include "absl/strings/string_view.h" -#include "http2/hpack/decoder/hpack_decoder_string_buffer.h" -#include "http2/hpack/decoder/hpack_decoding_error.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -class QUICHE_EXPORT_PRIVATE HpackWholeEntryListener { - public: - virtual ~HpackWholeEntryListener(); - - // Called when an indexed header (i.e. one in the static or dynamic table) has - // been decoded from an HPACK block. index is supposed to be non-zero, but - // that has not been checked by the caller. - virtual void OnIndexedHeader(size_t index) = 0; - - // Called when a header entry with a name index and literal value has - // been fully decoded from an HPACK block. name_index is NOT zero. - // entry_type will be kIndexedLiteralHeader, kUnindexedLiteralHeader, or - // kNeverIndexedLiteralHeader. - virtual void OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) = 0; - - // Called when a header entry with a literal name and literal value - // has been fully decoded from an HPACK block. entry_type will be - // kIndexedLiteralHeader, kUnindexedLiteralHeader, or - // kNeverIndexedLiteralHeader. - virtual void OnLiteralNameAndValue( - HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) = 0; - - // Called when an update to the size of the peer's dynamic table has been - // decoded. - virtual void OnDynamicTableSizeUpdate(size_t size) = 0; - - // OnHpackDecodeError is called if an error is detected while decoding. - virtual void OnHpackDecodeError(HpackDecodingError error, - std::string detailed_error) = 0; -}; - -// A no-op implementation of HpackWholeEntryDecoderListener, useful for ignoring -// callbacks once an error is detected. -class HpackWholeEntryNoOpListener : public HpackWholeEntryListener { - public: - ~HpackWholeEntryNoOpListener() override; - - void OnIndexedHeader(size_t index) override; - void OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) override; - void OnLiteralNameAndValue(HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) override; - void OnDynamicTableSizeUpdate(size_t size) override; - void OnHpackDecodeError(HpackDecodingError error, - std::string detailed_error) override; - - // Returns a listener that ignores all the calls. - static HpackWholeEntryNoOpListener* NoOpListener(); -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/hpack_static_table_entries.inc b/chromium/net/third_party/quiche/src/http2/hpack/hpack_static_table_entries.inc deleted file mode 100644 index c6ae125f3b2..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/hpack_static_table_entries.inc +++ /dev/null @@ -1,65 +0,0 @@ -// This file is designed to be included by C/C++ files which need the contents -// of the HPACK static table. It may be included more than once if necessary. -// See http://httpwg.org/specs/rfc7541.html#static.table.definition - -STATIC_TABLE_ENTRY(":authority", "", 1); -STATIC_TABLE_ENTRY(":method", "GET", 2); -STATIC_TABLE_ENTRY(":method", "POST", 3); -STATIC_TABLE_ENTRY(":path", "/", 4); -STATIC_TABLE_ENTRY(":path", "/index.html", 5); -STATIC_TABLE_ENTRY(":scheme", "http", 6); -STATIC_TABLE_ENTRY(":scheme", "https", 7); -STATIC_TABLE_ENTRY(":status", "200", 8); -STATIC_TABLE_ENTRY(":status", "204", 9); -STATIC_TABLE_ENTRY(":status", "206", 10); -STATIC_TABLE_ENTRY(":status", "304", 11); -STATIC_TABLE_ENTRY(":status", "400", 12); -STATIC_TABLE_ENTRY(":status", "404", 13); -STATIC_TABLE_ENTRY(":status", "500", 14); -STATIC_TABLE_ENTRY("accept-charset", "", 15); -STATIC_TABLE_ENTRY("accept-encoding", "gzip, deflate", 16); -STATIC_TABLE_ENTRY("accept-language", "", 17); -STATIC_TABLE_ENTRY("accept-ranges", "", 18); -STATIC_TABLE_ENTRY("accept", "", 19); -STATIC_TABLE_ENTRY("access-control-allow-origin", "", 20); -STATIC_TABLE_ENTRY("age", "", 21); -STATIC_TABLE_ENTRY("allow", "", 22); -STATIC_TABLE_ENTRY("authorization", "", 23); -STATIC_TABLE_ENTRY("cache-control", "", 24); -STATIC_TABLE_ENTRY("content-disposition", "", 25); -STATIC_TABLE_ENTRY("content-encoding", "", 26); -STATIC_TABLE_ENTRY("content-language", "", 27); -STATIC_TABLE_ENTRY("content-length", "", 28); -STATIC_TABLE_ENTRY("content-location", "", 29); -STATIC_TABLE_ENTRY("content-range", "", 30); -STATIC_TABLE_ENTRY("content-type", "", 31); -STATIC_TABLE_ENTRY("cookie", "", 32); -STATIC_TABLE_ENTRY("date", "", 33); -STATIC_TABLE_ENTRY("etag", "", 34); -STATIC_TABLE_ENTRY("expect", "", 35); -STATIC_TABLE_ENTRY("expires", "", 36); -STATIC_TABLE_ENTRY("from", "", 37); -STATIC_TABLE_ENTRY("host", "", 38); -STATIC_TABLE_ENTRY("if-match", "", 39); -STATIC_TABLE_ENTRY("if-modified-since", "", 40); -STATIC_TABLE_ENTRY("if-none-match", "", 41); -STATIC_TABLE_ENTRY("if-range", "", 42); -STATIC_TABLE_ENTRY("if-unmodified-since", "", 43); -STATIC_TABLE_ENTRY("last-modified", "", 44); -STATIC_TABLE_ENTRY("link", "", 45); -STATIC_TABLE_ENTRY("location", "", 46); -STATIC_TABLE_ENTRY("max-forwards", "", 47); -STATIC_TABLE_ENTRY("proxy-authenticate", "", 48); -STATIC_TABLE_ENTRY("proxy-authorization", "", 49); -STATIC_TABLE_ENTRY("range", "", 50); -STATIC_TABLE_ENTRY("referer", "", 51); -STATIC_TABLE_ENTRY("refresh", "", 52); -STATIC_TABLE_ENTRY("retry-after", "", 53); -STATIC_TABLE_ENTRY("server", "", 54); -STATIC_TABLE_ENTRY("set-cookie", "", 55); -STATIC_TABLE_ENTRY("strict-transport-security", "", 56); -STATIC_TABLE_ENTRY("transfer-encoding", "", 57); -STATIC_TABLE_ENTRY("user-agent", "", 58); -STATIC_TABLE_ENTRY("vary", "", 59); -STATIC_TABLE_ENTRY("via", "", 60); -STATIC_TABLE_ENTRY("www-authenticate", "", 61); diff --git a/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants.cc b/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants.cc deleted file mode 100644 index e02ef9bcea8..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants.cc +++ /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. - -#include "http2/hpack/http2_hpack_constants.h" - -#include "absl/strings/str_cat.h" - -namespace http2 { - -std::string HpackEntryTypeToString(HpackEntryType v) { - switch (v) { - case HpackEntryType::kIndexedHeader: - return "kIndexedHeader"; - case HpackEntryType::kDynamicTableSizeUpdate: - return "kDynamicTableSizeUpdate"; - case HpackEntryType::kIndexedLiteralHeader: - return "kIndexedLiteralHeader"; - case HpackEntryType::kUnindexedLiteralHeader: - return "kUnindexedLiteralHeader"; - case HpackEntryType::kNeverIndexedLiteralHeader: - return "kNeverIndexedLiteralHeader"; - } - return absl::StrCat("UnknownHpackEntryType(", static_cast<int>(v), ")"); -} - -std::ostream& operator<<(std::ostream& out, HpackEntryType v) { - return out << HpackEntryTypeToString(v); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants.h b/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants.h deleted file mode 100644 index ba83ba34cd3..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants.h +++ /dev/null @@ -1,63 +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_HPACK_HTTP2_HPACK_CONSTANTS_H_ -#define QUICHE_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_ - -// Enum HpackEntryType identifies the 5 basic types of HPACK Block Entries. -// -// See the spec for details: -// https://http2.github.io/http2-spec/compression.html#rfc.section.6 - -#include <ostream> -#include <string> - -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -const size_t kFirstDynamicTableIndex = 62; - -enum class HpackEntryType { - // Entry is an index into the static or dynamic table. Decoding it has no - // effect on the dynamic table. - kIndexedHeader, - - // The entry contains a literal value. The name may be either a literal or a - // reference to an entry in the static or dynamic table. - // The entry is added to the dynamic table after decoding. - kIndexedLiteralHeader, - - // The entry contains a literal value. The name may be either a literal or a - // reference to an entry in the static or dynamic table. - // The entry is not added to the dynamic table after decoding, but a proxy - // may choose to insert the entry into its dynamic table when forwarding - // to another endpoint. - kUnindexedLiteralHeader, - - // The entry contains a literal value. The name may be either a literal or a - // reference to an entry in the static or dynamic table. - // The entry is not added to the dynamic table after decoding, and a proxy - // must NOT insert the entry into its dynamic table when forwarding to another - // endpoint. - kNeverIndexedLiteralHeader, - - // Entry conveys the size limit of the dynamic table of the encoder to - // the decoder. May be used to flush the table by sending a zero and then - // resetting the size back up to the maximum that the encoder will use - // (within the limits of SETTINGS_HEADER_TABLE_SIZE sent by the - // decoder to the encoder, with the default of 4096 assumed). - kDynamicTableSizeUpdate, -}; - -// Returns the name of the enum member. -QUICHE_EXPORT_PRIVATE std::string HpackEntryTypeToString(HpackEntryType v); - -// Inserts the name of the enum member into |out|. -QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - HpackEntryType v); - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants_test.cc deleted file mode 100644 index 1c3dd109d95..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/http2_hpack_constants_test.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/hpack/http2_hpack_constants.h" - -#include <sstream> - -#include "http2/platform/api/http2_logging.h" -#include "http2/platform/api/http2_test_helpers.h" - -namespace http2 { -namespace test { -namespace { - -TEST(HpackEntryTypeTest, HpackEntryTypeToString) { - EXPECT_EQ("kIndexedHeader", - HpackEntryTypeToString(HpackEntryType::kIndexedHeader)); - EXPECT_EQ("kDynamicTableSizeUpdate", - HpackEntryTypeToString(HpackEntryType::kDynamicTableSizeUpdate)); - EXPECT_EQ("kIndexedLiteralHeader", - HpackEntryTypeToString(HpackEntryType::kIndexedLiteralHeader)); - EXPECT_EQ("kUnindexedLiteralHeader", - HpackEntryTypeToString(HpackEntryType::kUnindexedLiteralHeader)); - EXPECT_EQ("kNeverIndexedLiteralHeader", - HpackEntryTypeToString(HpackEntryType::kNeverIndexedLiteralHeader)); - EXPECT_EQ("UnknownHpackEntryType(12321)", - HpackEntryTypeToString(static_cast<HpackEntryType>(12321))); -} - -TEST(HpackEntryTypeTest, OutputHpackEntryType) { - { - std::stringstream log; - log << HpackEntryType::kIndexedHeader; - EXPECT_EQ("kIndexedHeader", log.str()); - } - { - std::stringstream log; - log << HpackEntryType::kDynamicTableSizeUpdate; - EXPECT_EQ("kDynamicTableSizeUpdate", log.str()); - } - { - std::stringstream log; - log << HpackEntryType::kIndexedLiteralHeader; - EXPECT_EQ("kIndexedLiteralHeader", log.str()); - } - { - std::stringstream log; - log << HpackEntryType::kUnindexedLiteralHeader; - EXPECT_EQ("kUnindexedLiteralHeader", log.str()); - } - { - std::stringstream log; - log << HpackEntryType::kNeverIndexedLiteralHeader; - EXPECT_EQ("kNeverIndexedLiteralHeader", log.str()); - } - { - std::stringstream log; - log << static_cast<HpackEntryType>(1234321); - EXPECT_EQ("UnknownHpackEntryType(1234321)", log.str()); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.cc deleted file mode 100644 index 2f486c64dba..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.cc +++ /dev/null @@ -1,485 +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/hpack/huffman/hpack_huffman_decoder.h" - -#include <bitset> -#include <limits> - -#include "http2/platform/api/http2_logging.h" - -// Terminology: -// -// Symbol - a plain text (unencoded) character (uint8), or the End-of-String -// (EOS) symbol, 256. -// -// Code - the sequence of bits used to encode a symbol, varying in length from -// 5 bits for the most common symbols (e.g. '0', '1', and 'a'), to -// 30 bits for the least common (e.g. the EOS symbol). -// For those symbols whose codes have the same length, their code values -// are sorted such that the lower symbol value has a lower code value. -// -// Canonical - a symbol's cardinal value when sorted first by code length, and -// then by symbol value. For example, canonical 0 is for ASCII '0' -// (uint8 value 0x30), which is the first of the symbols whose code -// is 5 bits long, and the last canonical is EOS, which is the last -// of the symbols whose code is 30 bits long. - -namespace http2 { -namespace { - -// HuffmanCode is used to store the codes associated with symbols (a pattern of -// from 5 to 30 bits). -typedef uint32_t HuffmanCode; - -// HuffmanCodeBitCount is used to store a count of bits in a code. -typedef uint16_t HuffmanCodeBitCount; - -// HuffmanCodeBitSet is used for producing a string version of a code because -// std::bitset logs nicely. -typedef std::bitset<32> HuffmanCodeBitSet; -typedef std::bitset<64> HuffmanAccumulatorBitSet; - -static constexpr HuffmanCodeBitCount kMinCodeBitCount = 5; -static constexpr HuffmanCodeBitCount kMaxCodeBitCount = 30; -static constexpr HuffmanCodeBitCount kHuffmanCodeBitCount = - std::numeric_limits<HuffmanCode>::digits; - -static_assert(std::numeric_limits<HuffmanCode>::digits >= kMaxCodeBitCount, - "HuffmanCode isn't big enough."); - -static_assert(std::numeric_limits<HuffmanAccumulator>::digits >= - kMaxCodeBitCount, - "HuffmanAccumulator isn't big enough."); - -static constexpr HuffmanAccumulatorBitCount kHuffmanAccumulatorBitCount = - std::numeric_limits<HuffmanAccumulator>::digits; -static constexpr HuffmanAccumulatorBitCount kExtraAccumulatorBitCount = - kHuffmanAccumulatorBitCount - kHuffmanCodeBitCount; - -// PrefixInfo holds info about a group of codes that are all of the same length. -struct PrefixInfo { - // Given the leading bits (32 in this case) of the encoded string, and that - // they start with a code of length |code_length|, return the corresponding - // canonical for that leading code. - uint32_t DecodeToCanonical(HuffmanCode bits) const { - // What is the position of the canonical symbol being decoded within - // the canonical symbols of |length|? - HuffmanCode ordinal_in_length = - ((bits - first_code) >> (kHuffmanCodeBitCount - code_length)); - - // Combined with |canonical| to produce the position of the canonical symbol - // being decoded within all of the canonical symbols. - return first_canonical + ordinal_in_length; - } - - const HuffmanCode first_code; // First code of this length, left justified in - // the field (i.e. the first bit of the code is - // the high-order bit). - const uint16_t code_length; // Length of the prefix code |base|. - const uint16_t first_canonical; // First canonical symbol of this length. -}; - -inline std::ostream& operator<<(std::ostream& out, const PrefixInfo& v) { - return out << "{first_code: " << HuffmanCodeBitSet(v.first_code) - << ", code_length: " << v.code_length - << ", first_canonical: " << v.first_canonical << "}"; -} - -// Given |value|, a sequence of the leading bits remaining to be decoded, -// figure out which group of canonicals (by code length) that value starts -// with. This function was generated. -PrefixInfo PrefixToInfo(HuffmanCode value) { - if (value < 0b10111000000000000000000000000000) { - if (value < 0b01010000000000000000000000000000) { - return {0b00000000000000000000000000000000, 5, 0}; - } else { - return {0b01010000000000000000000000000000, 6, 10}; - } - } else { - if (value < 0b11111110000000000000000000000000) { - if (value < 0b11111000000000000000000000000000) { - return {0b10111000000000000000000000000000, 7, 36}; - } else { - return {0b11111000000000000000000000000000, 8, 68}; - } - } else { - if (value < 0b11111111110000000000000000000000) { - if (value < 0b11111111101000000000000000000000) { - if (value < 0b11111111010000000000000000000000) { - return {0b11111110000000000000000000000000, 10, 74}; - } else { - return {0b11111111010000000000000000000000, 11, 79}; - } - } else { - return {0b11111111101000000000000000000000, 12, 82}; - } - } else { - if (value < 0b11111111111111100000000000000000) { - if (value < 0b11111111111110000000000000000000) { - if (value < 0b11111111111100000000000000000000) { - return {0b11111111110000000000000000000000, 13, 84}; - } else { - return {0b11111111111100000000000000000000, 14, 90}; - } - } else { - return {0b11111111111110000000000000000000, 15, 92}; - } - } else { - if (value < 0b11111111111111110100100000000000) { - if (value < 0b11111111111111101110000000000000) { - if (value < 0b11111111111111100110000000000000) { - return {0b11111111111111100000000000000000, 19, 95}; - } else { - return {0b11111111111111100110000000000000, 20, 98}; - } - } else { - return {0b11111111111111101110000000000000, 21, 106}; - } - } else { - if (value < 0b11111111111111111110101000000000) { - if (value < 0b11111111111111111011000000000000) { - return {0b11111111111111110100100000000000, 22, 119}; - } else { - return {0b11111111111111111011000000000000, 23, 145}; - } - } else { - if (value < 0b11111111111111111111101111000000) { - if (value < 0b11111111111111111111100000000000) { - if (value < 0b11111111111111111111011000000000) { - return {0b11111111111111111110101000000000, 24, 174}; - } else { - return {0b11111111111111111111011000000000, 25, 186}; - } - } else { - return {0b11111111111111111111100000000000, 26, 190}; - } - } else { - if (value < 0b11111111111111111111111111110000) { - if (value < 0b11111111111111111111111000100000) { - return {0b11111111111111111111101111000000, 27, 205}; - } else { - return {0b11111111111111111111111000100000, 28, 224}; - } - } else { - return {0b11111111111111111111111111110000, 30, 253}; - } - } - } - } - } - } - } - } -} - -// Mapping from canonical symbol (0 to 255) to actual symbol. -// clang-format off -constexpr unsigned char kCanonicalToSymbol[] = { - '0', '1', '2', 'a', 'c', 'e', 'i', 'o', - 's', 't', 0x20, '%', '-', '.', '/', '3', - '4', '5', '6', '7', '8', '9', '=', 'A', - '_', 'b', 'd', 'f', 'g', 'h', 'l', 'm', - 'n', 'p', 'r', 'u', ':', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'Y', 'j', 'k', 'q', 'v', - 'w', 'x', 'y', 'z', '&', '*', ',', ';', - 'X', 'Z', '!', '\"', '(', ')', '?', '\'', - '+', '|', '#', '>', 0x00, '$', '@', '[', - ']', '~', '^', '}', '<', '`', '{', '\\', - 0xc3, 0xd0, 0x80, 0x82, 0x83, 0xa2, 0xb8, 0xc2, - 0xe0, 0xe2, 0x99, 0xa1, 0xa7, 0xac, 0xb0, 0xb1, - 0xb3, 0xd1, 0xd8, 0xd9, 0xe3, 0xe5, 0xe6, 0x81, - 0x84, 0x85, 0x86, 0x88, 0x92, 0x9a, 0x9c, 0xa0, - 0xa3, 0xa4, 0xa9, 0xaa, 0xad, 0xb2, 0xb5, 0xb9, - 0xba, 0xbb, 0xbd, 0xbe, 0xc4, 0xc6, 0xe4, 0xe8, - 0xe9, 0x01, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, - 0x8f, 0x93, 0x95, 0x96, 0x97, 0x98, 0x9b, 0x9d, - 0x9e, 0xa5, 0xa6, 0xa8, 0xae, 0xaf, 0xb4, 0xb6, - 0xb7, 0xbc, 0xbf, 0xc5, 0xe7, 0xef, 0x09, 0x8e, - 0x90, 0x91, 0x94, 0x9f, 0xab, 0xce, 0xd7, 0xe1, - 0xec, 0xed, 0xc7, 0xcf, 0xea, 0xeb, 0xc0, 0xc1, - 0xc8, 0xc9, 0xca, 0xcd, 0xd2, 0xd5, 0xda, 0xdb, - 0xee, 0xf0, 0xf2, 0xf3, 0xff, 0xcb, 0xcc, 0xd3, - 0xd4, 0xd6, 0xdd, 0xde, 0xdf, 0xf1, 0xf4, 0xf5, - 0xf6, 0xf7, 0xf8, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0b, - 0x0c, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x7f, 0xdc, 0xf9, 0x0a, 0x0d, 0x16, -}; -// clang-format on - -constexpr size_t kShortCodeTableSize = 124; -struct ShortCodeInfo { - uint8_t symbol; - uint8_t length; -} kShortCodeTable[kShortCodeTableSize] = { - {0x30, 5}, // Match: 0b0000000, Symbol: 0 - {0x30, 5}, // Match: 0b0000001, Symbol: 0 - {0x30, 5}, // Match: 0b0000010, Symbol: 0 - {0x30, 5}, // Match: 0b0000011, Symbol: 0 - {0x31, 5}, // Match: 0b0000100, Symbol: 1 - {0x31, 5}, // Match: 0b0000101, Symbol: 1 - {0x31, 5}, // Match: 0b0000110, Symbol: 1 - {0x31, 5}, // Match: 0b0000111, Symbol: 1 - {0x32, 5}, // Match: 0b0001000, Symbol: 2 - {0x32, 5}, // Match: 0b0001001, Symbol: 2 - {0x32, 5}, // Match: 0b0001010, Symbol: 2 - {0x32, 5}, // Match: 0b0001011, Symbol: 2 - {0x61, 5}, // Match: 0b0001100, Symbol: a - {0x61, 5}, // Match: 0b0001101, Symbol: a - {0x61, 5}, // Match: 0b0001110, Symbol: a - {0x61, 5}, // Match: 0b0001111, Symbol: a - {0x63, 5}, // Match: 0b0010000, Symbol: c - {0x63, 5}, // Match: 0b0010001, Symbol: c - {0x63, 5}, // Match: 0b0010010, Symbol: c - {0x63, 5}, // Match: 0b0010011, Symbol: c - {0x65, 5}, // Match: 0b0010100, Symbol: e - {0x65, 5}, // Match: 0b0010101, Symbol: e - {0x65, 5}, // Match: 0b0010110, Symbol: e - {0x65, 5}, // Match: 0b0010111, Symbol: e - {0x69, 5}, // Match: 0b0011000, Symbol: i - {0x69, 5}, // Match: 0b0011001, Symbol: i - {0x69, 5}, // Match: 0b0011010, Symbol: i - {0x69, 5}, // Match: 0b0011011, Symbol: i - {0x6f, 5}, // Match: 0b0011100, Symbol: o - {0x6f, 5}, // Match: 0b0011101, Symbol: o - {0x6f, 5}, // Match: 0b0011110, Symbol: o - {0x6f, 5}, // Match: 0b0011111, Symbol: o - {0x73, 5}, // Match: 0b0100000, Symbol: s - {0x73, 5}, // Match: 0b0100001, Symbol: s - {0x73, 5}, // Match: 0b0100010, Symbol: s - {0x73, 5}, // Match: 0b0100011, Symbol: s - {0x74, 5}, // Match: 0b0100100, Symbol: t - {0x74, 5}, // Match: 0b0100101, Symbol: t - {0x74, 5}, // Match: 0b0100110, Symbol: t - {0x74, 5}, // Match: 0b0100111, Symbol: t - {0x20, 6}, // Match: 0b0101000, Symbol: (space) - {0x20, 6}, // Match: 0b0101001, Symbol: (space) - {0x25, 6}, // Match: 0b0101010, Symbol: % - {0x25, 6}, // Match: 0b0101011, Symbol: % - {0x2d, 6}, // Match: 0b0101100, Symbol: - - {0x2d, 6}, // Match: 0b0101101, Symbol: - - {0x2e, 6}, // Match: 0b0101110, Symbol: . - {0x2e, 6}, // Match: 0b0101111, Symbol: . - {0x2f, 6}, // Match: 0b0110000, Symbol: / - {0x2f, 6}, // Match: 0b0110001, Symbol: / - {0x33, 6}, // Match: 0b0110010, Symbol: 3 - {0x33, 6}, // Match: 0b0110011, Symbol: 3 - {0x34, 6}, // Match: 0b0110100, Symbol: 4 - {0x34, 6}, // Match: 0b0110101, Symbol: 4 - {0x35, 6}, // Match: 0b0110110, Symbol: 5 - {0x35, 6}, // Match: 0b0110111, Symbol: 5 - {0x36, 6}, // Match: 0b0111000, Symbol: 6 - {0x36, 6}, // Match: 0b0111001, Symbol: 6 - {0x37, 6}, // Match: 0b0111010, Symbol: 7 - {0x37, 6}, // Match: 0b0111011, Symbol: 7 - {0x38, 6}, // Match: 0b0111100, Symbol: 8 - {0x38, 6}, // Match: 0b0111101, Symbol: 8 - {0x39, 6}, // Match: 0b0111110, Symbol: 9 - {0x39, 6}, // Match: 0b0111111, Symbol: 9 - {0x3d, 6}, // Match: 0b1000000, Symbol: = - {0x3d, 6}, // Match: 0b1000001, Symbol: = - {0x41, 6}, // Match: 0b1000010, Symbol: A - {0x41, 6}, // Match: 0b1000011, Symbol: A - {0x5f, 6}, // Match: 0b1000100, Symbol: _ - {0x5f, 6}, // Match: 0b1000101, Symbol: _ - {0x62, 6}, // Match: 0b1000110, Symbol: b - {0x62, 6}, // Match: 0b1000111, Symbol: b - {0x64, 6}, // Match: 0b1001000, Symbol: d - {0x64, 6}, // Match: 0b1001001, Symbol: d - {0x66, 6}, // Match: 0b1001010, Symbol: f - {0x66, 6}, // Match: 0b1001011, Symbol: f - {0x67, 6}, // Match: 0b1001100, Symbol: g - {0x67, 6}, // Match: 0b1001101, Symbol: g - {0x68, 6}, // Match: 0b1001110, Symbol: h - {0x68, 6}, // Match: 0b1001111, Symbol: h - {0x6c, 6}, // Match: 0b1010000, Symbol: l - {0x6c, 6}, // Match: 0b1010001, Symbol: l - {0x6d, 6}, // Match: 0b1010010, Symbol: m - {0x6d, 6}, // Match: 0b1010011, Symbol: m - {0x6e, 6}, // Match: 0b1010100, Symbol: n - {0x6e, 6}, // Match: 0b1010101, Symbol: n - {0x70, 6}, // Match: 0b1010110, Symbol: p - {0x70, 6}, // Match: 0b1010111, Symbol: p - {0x72, 6}, // Match: 0b1011000, Symbol: r - {0x72, 6}, // Match: 0b1011001, Symbol: r - {0x75, 6}, // Match: 0b1011010, Symbol: u - {0x75, 6}, // Match: 0b1011011, Symbol: u - {0x3a, 7}, // Match: 0b1011100, Symbol: : - {0x42, 7}, // Match: 0b1011101, Symbol: B - {0x43, 7}, // Match: 0b1011110, Symbol: C - {0x44, 7}, // Match: 0b1011111, Symbol: D - {0x45, 7}, // Match: 0b1100000, Symbol: E - {0x46, 7}, // Match: 0b1100001, Symbol: F - {0x47, 7}, // Match: 0b1100010, Symbol: G - {0x48, 7}, // Match: 0b1100011, Symbol: H - {0x49, 7}, // Match: 0b1100100, Symbol: I - {0x4a, 7}, // Match: 0b1100101, Symbol: J - {0x4b, 7}, // Match: 0b1100110, Symbol: K - {0x4c, 7}, // Match: 0b1100111, Symbol: L - {0x4d, 7}, // Match: 0b1101000, Symbol: M - {0x4e, 7}, // Match: 0b1101001, Symbol: N - {0x4f, 7}, // Match: 0b1101010, Symbol: O - {0x50, 7}, // Match: 0b1101011, Symbol: P - {0x51, 7}, // Match: 0b1101100, Symbol: Q - {0x52, 7}, // Match: 0b1101101, Symbol: R - {0x53, 7}, // Match: 0b1101110, Symbol: S - {0x54, 7}, // Match: 0b1101111, Symbol: T - {0x55, 7}, // Match: 0b1110000, Symbol: U - {0x56, 7}, // Match: 0b1110001, Symbol: V - {0x57, 7}, // Match: 0b1110010, Symbol: W - {0x59, 7}, // Match: 0b1110011, Symbol: Y - {0x6a, 7}, // Match: 0b1110100, Symbol: j - {0x6b, 7}, // Match: 0b1110101, Symbol: k - {0x71, 7}, // Match: 0b1110110, Symbol: q - {0x76, 7}, // Match: 0b1110111, Symbol: v - {0x77, 7}, // Match: 0b1111000, Symbol: w - {0x78, 7}, // Match: 0b1111001, Symbol: x - {0x79, 7}, // Match: 0b1111010, Symbol: y - {0x7a, 7}, // Match: 0b1111011, Symbol: z -}; - -} // namespace - -HuffmanBitBuffer::HuffmanBitBuffer() { - Reset(); -} - -void HuffmanBitBuffer::Reset() { - accumulator_ = 0; - count_ = 0; -} - -size_t HuffmanBitBuffer::AppendBytes(absl::string_view input) { - HuffmanAccumulatorBitCount free_cnt = free_count(); - size_t bytes_available = input.size(); - if (free_cnt < 8 || bytes_available == 0) { - return 0; - } - - // Top up |accumulator_| until there isn't room for a whole byte. - size_t bytes_used = 0; - auto* ptr = reinterpret_cast<const uint8_t*>(input.data()); - do { - auto b = static_cast<HuffmanAccumulator>(*ptr++); - free_cnt -= 8; - accumulator_ |= (b << free_cnt); - ++bytes_used; - } while (free_cnt >= 8 && bytes_used < bytes_available); - count_ += (bytes_used * 8); - return bytes_used; -} - -HuffmanAccumulatorBitCount HuffmanBitBuffer::free_count() const { - return kHuffmanAccumulatorBitCount - count_; -} - -void HuffmanBitBuffer::ConsumeBits(HuffmanAccumulatorBitCount code_length) { - QUICHE_DCHECK_LE(code_length, count_); - accumulator_ <<= code_length; - count_ -= code_length; -} - -bool HuffmanBitBuffer::InputProperlyTerminated() const { - auto cnt = count(); - if (cnt < 8) { - if (cnt == 0) { - return true; - } - HuffmanAccumulator expected = ~(~HuffmanAccumulator() >> cnt); - // We expect all the bits below the high order |cnt| bits of accumulator_ - // to be cleared as we perform left shift operations while decoding. - QUICHE_DCHECK_EQ(accumulator_ & ~expected, 0u) - << "\n expected: " << HuffmanAccumulatorBitSet(expected) << "\n " - << *this; - return accumulator_ == expected; - } - return false; -} - -std::string HuffmanBitBuffer::DebugString() const { - std::stringstream ss; - ss << "{accumulator: " << HuffmanAccumulatorBitSet(accumulator_) - << "; count: " << count_ << "}"; - return ss.str(); -} - -HpackHuffmanDecoder::HpackHuffmanDecoder() = default; - -HpackHuffmanDecoder::~HpackHuffmanDecoder() = default; - -bool HpackHuffmanDecoder::Decode(absl::string_view input, std::string* output) { - HTTP2_DVLOG(1) << "HpackHuffmanDecoder::Decode"; - - // Fill bit_buffer_ from input. - input.remove_prefix(bit_buffer_.AppendBytes(input)); - - while (true) { - HTTP2_DVLOG(3) << "Enter Decode Loop, bit_buffer_: " << bit_buffer_; - if (bit_buffer_.count() >= 7) { - // Get high 7 bits of the bit buffer, see if that contains a complete - // code of 5, 6 or 7 bits. - uint8_t short_code = - bit_buffer_.value() >> (kHuffmanAccumulatorBitCount - 7); - QUICHE_DCHECK_LT(short_code, 128); - if (short_code < kShortCodeTableSize) { - ShortCodeInfo info = kShortCodeTable[short_code]; - bit_buffer_.ConsumeBits(info.length); - output->push_back(static_cast<char>(info.symbol)); - continue; - } - // The code is more than 7 bits long. Use PrefixToInfo, etc. to decode - // longer codes. - } else { - // We may have (mostly) drained bit_buffer_. If we can top it up, try - // using the table decoder above. - size_t byte_count = bit_buffer_.AppendBytes(input); - if (byte_count > 0) { - input.remove_prefix(byte_count); - continue; - } - } - - HuffmanCode code_prefix = bit_buffer_.value() >> kExtraAccumulatorBitCount; - HTTP2_DVLOG(3) << "code_prefix: " << HuffmanCodeBitSet(code_prefix); - - PrefixInfo prefix_info = PrefixToInfo(code_prefix); - HTTP2_DVLOG(3) << "prefix_info: " << prefix_info; - QUICHE_DCHECK_LE(kMinCodeBitCount, prefix_info.code_length); - QUICHE_DCHECK_LE(prefix_info.code_length, kMaxCodeBitCount); - - if (prefix_info.code_length <= bit_buffer_.count()) { - // We have enough bits for one code. - uint32_t canonical = prefix_info.DecodeToCanonical(code_prefix); - if (canonical < 256) { - // Valid code. - char c = kCanonicalToSymbol[canonical]; - output->push_back(c); - bit_buffer_.ConsumeBits(prefix_info.code_length); - continue; - } - // Encoder is not supposed to explicity encode the EOS symbol. - HTTP2_DLOG(ERROR) << "EOS explicitly encoded!\n " << bit_buffer_ << "\n " - << prefix_info; - return false; - } - // bit_buffer_ doesn't have enough bits in it to decode the next symbol. - // Append to it as many bytes as are available AND fit. - size_t byte_count = bit_buffer_.AppendBytes(input); - if (byte_count == 0) { - QUICHE_DCHECK_EQ(input.size(), 0u); - return true; - } - input.remove_prefix(byte_count); - } -} - -std::string HpackHuffmanDecoder::DebugString() const { - return bit_buffer_.DebugString(); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h deleted file mode 100644 index 867982359d3..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h +++ /dev/null @@ -1,134 +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_HPACK_HUFFMAN_HPACK_HUFFMAN_DECODER_H_ -#define QUICHE_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_DECODER_H_ - -// HpackHuffmanDecoder is an incremental decoder of strings that have been -// encoded using the Huffman table defined in the HPACK spec. -// By incremental, we mean that the HpackHuffmanDecoder::Decode method does -// not require the entire string to be provided, and can instead decode the -// string as fragments of it become available (e.g. as HPACK block fragments -// are received for decoding by HpackEntryDecoder). - -#include <stddef.h> - -#include <cstdint> -#include <iosfwd> -#include <string> - -#include "absl/strings/string_view.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -// HuffmanAccumulator is used to store bits during decoding, e.g. next N bits -// that have not yet been decoded, but have been extracted from the encoded -// string). An advantage of using a uint64 for the accumulator -// is that it has room for the bits of the longest code plus the bits of a full -// byte; that means that when adding more bits to the accumulator, it can always -// be done in whole bytes. For example, if we currently have 26 bits in the -// accumulator, and need more to decode the current symbol, we can add a whole -// byte to the accumulator, and not have to do juggling with adding 6 bits (to -// reach 30), and then keep track of the last two bits we've not been able to -// add to the accumulator. -typedef uint64_t HuffmanAccumulator; -typedef size_t HuffmanAccumulatorBitCount; - -// HuffmanBitBuffer stores the leading edge of bits to be decoded. The high -// order bit of accumulator_ is the next bit to be decoded. -class QUICHE_EXPORT_PRIVATE HuffmanBitBuffer { - public: - HuffmanBitBuffer(); - - // Prepare for decoding a new Huffman encoded string. - void Reset(); - - // Add as many whole bytes to the accumulator (accumulator_) as possible, - // returning the number of bytes added. - size_t AppendBytes(absl::string_view input); - - // Get the bits of the accumulator. - HuffmanAccumulator value() const { return accumulator_; } - - // Number of bits of the encoded string that are in the accumulator - // (accumulator_). - HuffmanAccumulatorBitCount count() const { return count_; } - - // Are there no bits in the accumulator? - bool IsEmpty() const { return count_ == 0; } - - // Number of additional bits that can be added to the accumulator. - HuffmanAccumulatorBitCount free_count() const; - - // Consume the leading |code_length| bits of the accumulator. - void ConsumeBits(HuffmanAccumulatorBitCount code_length); - - // Are the contents valid for the end of a Huffman encoded string? The RFC - // states that EOS (end-of-string) symbol must not be explicitly encoded in - // the bit stream, but any unused bits in the final byte must be set to the - // prefix of the EOS symbol, which is all 1 bits. So there can be at most 7 - // such bits. - // Returns true if the bit buffer is empty, or contains at most 7 bits, all - // of them 1. Otherwise returns false. - bool InputProperlyTerminated() const; - - std::string DebugString() const; - - private: - HuffmanAccumulator accumulator_; - HuffmanAccumulatorBitCount count_; -}; - -inline std::ostream& operator<<(std::ostream& out, const HuffmanBitBuffer& v) { - return out << v.DebugString(); -} - -class QUICHE_EXPORT_PRIVATE HpackHuffmanDecoder { - public: - HpackHuffmanDecoder(); - ~HpackHuffmanDecoder(); - - // Prepare for decoding a new Huffman encoded string. - void Reset() { bit_buffer_.Reset(); } - - // Decode the portion of a HPACK Huffman encoded string that is in |input|, - // appending the decoded symbols into |*output|, stopping when more bits are - // needed to determine the next symbol, which/ means that the input has been - // drained, and also that the bit_buffer_ is empty or that the bits that are - // in it are not a whole symbol. - // If |input| is the start of a string, the caller must first call Reset. - // If |input| includes the end of the encoded string, the caller must call - // InputProperlyTerminated after Decode has returned true in order to - // determine if the encoded string was properly terminated. - // Returns false if something went wrong (e.g. the encoding contains the code - // EOS symbol). Otherwise returns true, in which case input has been fully - // decoded or buffered; in particular, if the low-order bit of the final byte - // of the input is not the last bit of an encoded symbol, then bit_buffer_ - // will contain the leading bits of the code for that symbol, but not the - // final bits of that code. - // Note that output should be empty, but that it is not cleared by Decode(). - bool Decode(absl::string_view input, std::string* output); - - // Is what remains in the bit_buffer_ valid at the end of an encoded string? - // Call after passing the the final portion of a Huffman string to Decode, - // and getting true as the result. - bool InputProperlyTerminated() const { - return bit_buffer_.InputProperlyTerminated(); - } - - std::string DebugString() const; - - private: - HuffmanBitBuffer bit_buffer_; -}; - -inline std::ostream& operator<<(std::ostream& out, - const HpackHuffmanDecoder& v) { - return out << v.DebugString(); -} - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc deleted file mode 100644 index 1e160862b22..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc +++ /dev/null @@ -1,242 +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/hpack/huffman/hpack_huffman_decoder.h" - -// Tests of HpackHuffmanDecoder and HuffmanBitBuffer. - -#include <iostream> - -#include "absl/base/macros.h" -#include "absl/strings/escaping.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/platform/api/http2_test_helpers.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -namespace { - -TEST(HuffmanBitBufferTest, Reset) { - HuffmanBitBuffer bb; - EXPECT_TRUE(bb.IsEmpty()); - EXPECT_TRUE(bb.InputProperlyTerminated()); - EXPECT_EQ(bb.count(), 0u); - EXPECT_EQ(bb.free_count(), 64u); - EXPECT_EQ(bb.value(), 0u); -} - -TEST(HuffmanBitBufferTest, AppendBytesAligned) { - std::string s; - s.push_back('\x11'); - s.push_back('\x22'); - s.push_back('\x33'); - absl::string_view sp(s); - - HuffmanBitBuffer bb; - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_TRUE(sp.empty()); - EXPECT_FALSE(bb.IsEmpty()) << bb; - EXPECT_FALSE(bb.InputProperlyTerminated()); - EXPECT_EQ(bb.count(), 24u) << bb; - EXPECT_EQ(bb.free_count(), 40u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x112233) << 40) << bb; - - s.clear(); - s.push_back('\x44'); - sp = s; - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_TRUE(sp.empty()); - EXPECT_EQ(bb.count(), 32u) << bb; - EXPECT_EQ(bb.free_count(), 32u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x11223344) << 32) << bb; - - s.clear(); - s.push_back('\x55'); - s.push_back('\x66'); - s.push_back('\x77'); - s.push_back('\x88'); - s.push_back('\x99'); - sp = s; - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 1u); - EXPECT_EQ('\x99', sp[0]); - EXPECT_EQ(bb.count(), 64u) << bb; - EXPECT_EQ(bb.free_count(), 0u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x1122334455667788LL)) << bb; - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 1u); - EXPECT_EQ('\x99', sp[0]); - EXPECT_EQ(bb.count(), 64u) << bb; - EXPECT_EQ(bb.free_count(), 0u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x1122334455667788LL)) << bb; -} - -TEST(HuffmanBitBufferTest, ConsumeBits) { - std::string s; - s.push_back('\x11'); - s.push_back('\x22'); - s.push_back('\x33'); - absl::string_view sp(s); - - HuffmanBitBuffer bb; - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_TRUE(sp.empty()); - - bb.ConsumeBits(1); - EXPECT_EQ(bb.count(), 23u) << bb; - EXPECT_EQ(bb.free_count(), 41u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x112233) << 41) << bb; - - bb.ConsumeBits(20); - EXPECT_EQ(bb.count(), 3u) << bb; - EXPECT_EQ(bb.free_count(), 61u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x3) << 61) << bb; -} - -TEST(HuffmanBitBufferTest, AppendBytesUnaligned) { - std::string s; - s.push_back('\x11'); - s.push_back('\x22'); - s.push_back('\x33'); - s.push_back('\x44'); - s.push_back('\x55'); - s.push_back('\x66'); - s.push_back('\x77'); - s.push_back('\x88'); - s.push_back('\x99'); - s.push_back('\xaa'); - s.push_back('\xbb'); - s.push_back('\xcc'); - s.push_back('\xdd'); - absl::string_view sp(s); - - HuffmanBitBuffer bb; - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 5u); - EXPECT_FALSE(bb.InputProperlyTerminated()); - - bb.ConsumeBits(15); - EXPECT_EQ(bb.count(), 49u) << bb; - EXPECT_EQ(bb.free_count(), 15u) << bb; - - HuffmanAccumulator expected(0x1122334455667788); - expected <<= 15; - EXPECT_EQ(bb.value(), expected); - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 4u); - EXPECT_EQ(bb.count(), 57u) << bb; - EXPECT_EQ(bb.free_count(), 7u) << bb; - - expected |= (HuffmanAccumulator(0x99) << 7); - EXPECT_EQ(bb.value(), expected) - << bb << std::hex << "\n actual: " << bb.value() - << "\n expected: " << expected; -} - -class HpackHuffmanDecoderTest : public RandomDecoderTest { - protected: - HpackHuffmanDecoderTest() { - // The decoder may return true, and its accumulator may be empty, at - // many boundaries while decoding, and yet the whole string hasn't - // been decoded. - stop_decode_on_done_ = false; - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - input_bytes_seen_ = 0; - output_buffer_.clear(); - decoder_.Reset(); - return ResumeDecoding(b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - input_bytes_seen_ += b->Remaining(); - absl::string_view sp(b->cursor(), b->Remaining()); - if (decoder_.Decode(sp, &output_buffer_)) { - b->AdvanceCursor(b->Remaining()); - // Successfully decoded (or buffered) the bytes in absl::string_view. - EXPECT_LE(input_bytes_seen_, input_bytes_expected_); - // Have we reached the end of the encoded string? - if (input_bytes_expected_ == input_bytes_seen_) { - if (decoder_.InputProperlyTerminated()) { - return DecodeStatus::kDecodeDone; - } else { - return DecodeStatus::kDecodeError; - } - } - return DecodeStatus::kDecodeInProgress; - } - return DecodeStatus::kDecodeError; - } - - HpackHuffmanDecoder decoder_; - std::string output_buffer_; - size_t input_bytes_seen_; - size_t input_bytes_expected_; -}; - -TEST_F(HpackHuffmanDecoderTest, SpecRequestExamples) { - HpackHuffmanDecoder decoder; - std::string test_table[] = { - absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff"), - "www.example.com", - absl::HexStringToBytes("a8eb10649cbf"), - "no-cache", - absl::HexStringToBytes("25a849e95ba97d7f"), - "custom-key", - absl::HexStringToBytes("25a849e95bb8e8b4bf"), - "custom-value", - }; - for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) { - const std::string& huffman_encoded(test_table[i]); - const std::string& plain_string(test_table[i + 1]); - std::string buffer; - decoder.Reset(); - EXPECT_TRUE(decoder.Decode(huffman_encoded, &buffer)) << decoder; - EXPECT_TRUE(decoder.InputProperlyTerminated()) << decoder; - EXPECT_EQ(buffer, plain_string); - } -} - -TEST_F(HpackHuffmanDecoderTest, SpecResponseExamples) { - HpackHuffmanDecoder decoder; - // clang-format off - std::string test_table[] = { - absl::HexStringToBytes("6402"), - "302", - absl::HexStringToBytes("aec3771a4b"), - "private", - absl::HexStringToBytes("d07abe941054d444a8200595040b8166" - "e082a62d1bff"), - "Mon, 21 Oct 2013 20:13:21 GMT", - absl::HexStringToBytes("9d29ad171863c78f0b97c8e9ae82ae43" - "d3"), - "https://www.example.com", - absl::HexStringToBytes("94e7821dd7f2e6c7b335dfdfcd5b3960" - "d5af27087f3672c1ab270fb5291f9587" - "316065c003ed4ee5b1063d5007"), - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", - }; - // clang-format on - for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) { - const std::string& huffman_encoded(test_table[i]); - const std::string& plain_string(test_table[i + 1]); - std::string buffer; - decoder.Reset(); - EXPECT_TRUE(decoder.Decode(huffman_encoded, &buffer)) << decoder; - EXPECT_TRUE(decoder.InputProperlyTerminated()) << decoder; - EXPECT_EQ(buffer, plain_string); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.cc deleted file mode 100644 index daf85bc44d5..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2018 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/hpack/huffman/hpack_huffman_encoder.h" - -#include "http2/hpack/huffman/huffman_spec_tables.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -size_t HuffmanSize(absl::string_view plain) { - size_t bits = 0; - for (const uint8_t c : plain) { - bits += HuffmanSpecTables::kCodeLengths[c]; - } - return (bits + 7) / 8; -} - -void HuffmanEncode(absl::string_view plain, - size_t encoded_size, - std::string* huffman) { - QUICHE_DCHECK(huffman != nullptr); - huffman->reserve(huffman->size() + encoded_size); - uint64_t bit_buffer = 0; // High-bit is next bit to output. Not clear if that - // is more performant than having the low-bit be the - // last to be output. - size_t bits_unused = 64; // Number of bits available for the next code. - for (uint8_t c : plain) { - size_t code_length = HuffmanSpecTables::kCodeLengths[c]; - if (bits_unused < code_length) { - // There isn't enough room in bit_buffer for the code of c. - // Flush until bits_unused > 56 (i.e. 64 - 8). - do { - char h = static_cast<char>(bit_buffer >> 56); - bit_buffer <<= 8; - bits_unused += 8; - // Perhaps would be more efficient if we populated an array of chars, - // so we don't have to call push_back each time. Reconsider if used - // for production. - huffman->push_back(h); - } while (bits_unused <= 56); - } - uint64_t code = HuffmanSpecTables::kRightCodes[c]; - size_t shift_by = bits_unused - code_length; - bit_buffer |= (code << shift_by); - bits_unused -= code_length; - } - // bit_buffer contains (64-bits_unused) bits that still need to be flushed. - // Output whole bytes until we don't have any whole bytes left. - size_t bits_used = 64 - bits_unused; - while (bits_used >= 8) { - char h = static_cast<char>(bit_buffer >> 56); - bit_buffer <<= 8; - bits_used -= 8; - huffman->push_back(h); - } - if (bits_used > 0) { - // We have less than a byte left to output. The spec calls for padding out - // the final byte with the leading bits of the EOS symbol (30 1-bits). - constexpr uint64_t leading_eos_bits = 0b11111111; - bit_buffer |= (leading_eos_bits << (56 - bits_used)); - char h = static_cast<char>(bit_buffer >> 56); - huffman->push_back(h); - } -} - -void HuffmanEncodeFast(absl::string_view input, - size_t encoded_size, - std::string* output) { - const size_t original_size = output->size(); - const size_t final_size = original_size + encoded_size; - // Reserve an extra four bytes to avoid accessing unallocated memory (even - // though it would only be OR'd with zeros and thus not modified). - output->resize(final_size + 4, 0); - - // Pointer to first appended byte. - char* const first = &*output->begin() + original_size; - size_t bit_counter = 0; - for (uint8_t c : input) { - // Align the Huffman code to byte boundaries as it needs to be written. - // The longest Huffman code is 30 bits long, and it can be shifted by up to - // 7 bits, requiring 37 bits in total. The most significant 25 bits and - // least significant 2 bits of |code| are always zero. - uint64_t code = static_cast<uint64_t>(HuffmanSpecTables::kLeftCodes[c]) - << (8 - (bit_counter % 8)); - // The byte where the first bit of |code| needs to be written. - char* const current = first + (bit_counter / 8); - - bit_counter += HuffmanSpecTables::kCodeLengths[c]; - - *current |= code >> 32; - - // Do not check if this write is zero before executing it, because with - // uniformly random shifts and an ideal random input distribution - // corresponding to the Huffman tree it would only be zero in 29% of the - // cases. - *(current + 1) |= (code >> 24) & 0xff; - - // Continue to next input character if there is nothing else to write. - // (If next byte is zero, then rest must also be zero.) - if ((code & 0xff0000) == 0) { - continue; - } - *(current + 2) |= (code >> 16) & 0xff; - - // Continue to next input character if there is nothing else to write. - // (If next byte is zero, then rest must also be zero.) - if ((code & 0xff00) == 0) { - continue; - } - *(current + 3) |= (code >> 8) & 0xff; - - // Do not check if this write is zero, because the check would probably be - // as expensive as the write. - *(current + 4) |= code & 0xff; - } - - QUICHE_DCHECK_EQ(encoded_size, (bit_counter + 7) / 8); - - // EOF - if (bit_counter % 8 != 0) { - *(first + encoded_size - 1) |= 0xff >> (bit_counter & 7); - } - - output->resize(final_size); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.h b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.h deleted file mode 100644 index a0ed8615129..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.h +++ /dev/null @@ -1,40 +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_HPACK_HUFFMAN_HPACK_HUFFMAN_ENCODER_H_ -#define QUICHE_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_ENCODER_H_ - -// Functions supporting the encoding of strings using the HPACK-defined Huffman -// table. - -#include <cstddef> // For size_t -#include <string> - -#include "absl/strings/string_view.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -// Returns the size of the Huffman encoding of |plain|, which may be greater -// than plain.size(). -QUICHE_EXPORT_PRIVATE size_t HuffmanSize(absl::string_view plain); - -// Encode the plain text string |plain| with the Huffman encoding defined in the -// HPACK RFC, 7541. |encoded_size| is used to pre-allocate storage and it -// should be the value returned by HuffmanSize(). Appends the result to -// |*huffman|. -QUICHE_EXPORT_PRIVATE void HuffmanEncode(absl::string_view plain, - size_t encoded_size, - std::string* huffman); - -// Encode |input| with the Huffman encoding defined RFC7541, used in HPACK and -// QPACK. |encoded_size| must be the value returned by HuffmanSize(). -// Appends the result to the end of |*output|. -QUICHE_EXPORT_PRIVATE void HuffmanEncodeFast(absl::string_view input, - size_t encoded_size, - std::string* output); - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_ENCODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc deleted file mode 100644 index 84439c16973..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) 2018 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/hpack/huffman/hpack_huffman_encoder.h" - -#include "absl/base/macros.h" -#include "absl/strings/escaping.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace { - -class HuffmanEncoderTest : public ::testing::TestWithParam<bool> { - protected: - HuffmanEncoderTest() : use_fast_encoder_(GetParam()) {} - virtual ~HuffmanEncoderTest() = default; - - void Encode(absl::string_view input, - size_t encoded_size, - std::string* output) { - use_fast_encoder_ ? HuffmanEncodeFast(input, encoded_size, output) - : HuffmanEncode(input, encoded_size, output); - } - - const bool use_fast_encoder_; -}; - -INSTANTIATE_TEST_SUITE_P(TwoEncoders, HuffmanEncoderTest, ::testing::Bool()); - -TEST_P(HuffmanEncoderTest, Empty) { - std::string empty(""); - size_t encoded_size = HuffmanSize(empty); - EXPECT_EQ(0u, encoded_size); - - std::string buffer; - Encode(empty, encoded_size, &buffer); - EXPECT_EQ("", buffer); -} - -TEST_P(HuffmanEncoderTest, SpecRequestExamples) { - std::string test_table[] = { - absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff"), - "www.example.com", - absl::HexStringToBytes("a8eb10649cbf"), - "no-cache", - absl::HexStringToBytes("25a849e95ba97d7f"), - "custom-key", - absl::HexStringToBytes("25a849e95bb8e8b4bf"), - "custom-value", - }; - for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) { - const std::string& huffman_encoded(test_table[i]); - const std::string& plain_string(test_table[i + 1]); - size_t encoded_size = HuffmanSize(plain_string); - EXPECT_EQ(huffman_encoded.size(), encoded_size); - std::string buffer; - buffer.reserve(); - Encode(plain_string, encoded_size, &buffer); - EXPECT_EQ(buffer, huffman_encoded) << "Error encoding " << plain_string; - } -} - -TEST_P(HuffmanEncoderTest, SpecResponseExamples) { - // clang-format off - std::string test_table[] = { - absl::HexStringToBytes("6402"), - "302", - absl::HexStringToBytes("aec3771a4b"), - "private", - absl::HexStringToBytes("d07abe941054d444a8200595040b8166" - "e082a62d1bff"), - "Mon, 21 Oct 2013 20:13:21 GMT", - absl::HexStringToBytes("9d29ad171863c78f0b97c8e9ae82ae43" - "d3"), - "https://www.example.com", - absl::HexStringToBytes("94e7821dd7f2e6c7b335dfdfcd5b3960" - "d5af27087f3672c1ab270fb5291f9587" - "316065c003ed4ee5b1063d5007"), - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", - }; - // clang-format on - for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) { - const std::string& huffman_encoded(test_table[i]); - const std::string& plain_string(test_table[i + 1]); - size_t encoded_size = HuffmanSize(plain_string); - EXPECT_EQ(huffman_encoded.size(), encoded_size); - std::string buffer; - Encode(plain_string, encoded_size, &buffer); - EXPECT_EQ(buffer, huffman_encoded) << "Error encoding " << plain_string; - } -} - -TEST_P(HuffmanEncoderTest, EncodedSizeAgreesWithEncodeString) { - std::string test_table[] = { - "", - "Mon, 21 Oct 2013 20:13:21 GMT", - "https://www.example.com", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", - std::string(1, '\0'), - std::string("foo\0bar", 7), - std::string(256, '\0'), - }; - // Modify last |test_table| entry to cover all codes. - for (size_t i = 0; i != 256; ++i) { - test_table[ABSL_ARRAYSIZE(test_table) - 1][i] = static_cast<char>(i); - } - - for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); ++i) { - const std::string& plain_string = test_table[i]; - size_t encoded_size = HuffmanSize(plain_string); - std::string huffman_encoded; - Encode(plain_string, encoded_size, &huffman_encoded); - EXPECT_EQ(encoded_size, huffman_encoded.size()); - } -} - -// Test that encoding appends to output without overwriting it. -TEST_P(HuffmanEncoderTest, AppendToOutput) { - size_t encoded_size = HuffmanSize("foo"); - std::string buffer; - Encode("foo", encoded_size, &buffer); - EXPECT_EQ(absl::HexStringToBytes("94e7"), buffer); - - encoded_size = HuffmanSize("bar"); - Encode("bar", encoded_size, &buffer); - EXPECT_EQ(absl::HexStringToBytes("94e78c767f"), buffer); -} - -} // namespace -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc deleted file mode 100644 index 671eb4f33a0..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2018 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. - -// A test of roundtrips through the encoder and decoder. - -#include <stddef.h> - -#include "absl/strings/string_view.h" -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/hpack/huffman/hpack_huffman_decoder.h" -#include "http2/hpack/huffman/hpack_huffman_encoder.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" -#include "common/quiche_text_utils.h" - -using ::testing::AssertionSuccess; -using ::testing::Combine; -using ::testing::Range; -using ::testing::Values; - -namespace http2 { -namespace test { -namespace { - -std::string GenAsciiNonControlSet() { - std::string s; - const char space = ' '; // First character after the control characters: 0x20 - const char del = 127; // First character after the non-control characters. - for (char c = space; c < del; ++c) { - s.push_back(c); - } - return s; -} - -class HpackHuffmanTranscoderTest : public RandomDecoderTest { - protected: - HpackHuffmanTranscoderTest() - : ascii_non_control_set_(GenAsciiNonControlSet()) { - // The decoder may return true, and its accumulator may be empty, at - // many boundaries while decoding, and yet the whole string hasn't - // been decoded. - stop_decode_on_done_ = false; - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - input_bytes_seen_ = 0; - output_buffer_.clear(); - decoder_.Reset(); - return ResumeDecoding(b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - input_bytes_seen_ += b->Remaining(); - absl::string_view sp(b->cursor(), b->Remaining()); - if (decoder_.Decode(sp, &output_buffer_)) { - b->AdvanceCursor(b->Remaining()); - // Successfully decoded (or buffered) the bytes in absl::string_view. - EXPECT_LE(input_bytes_seen_, input_bytes_expected_); - // Have we reached the end of the encoded string? - if (input_bytes_expected_ == input_bytes_seen_) { - if (decoder_.InputProperlyTerminated()) { - return DecodeStatus::kDecodeDone; - } else { - return DecodeStatus::kDecodeError; - } - } - return DecodeStatus::kDecodeInProgress; - } - return DecodeStatus::kDecodeError; - } - - AssertionResult TranscodeAndValidateSeveralWays( - absl::string_view plain, - absl::string_view expected_huffman) { - size_t encoded_size = HuffmanSize(plain); - std::string encoded; - HuffmanEncode(plain, encoded_size, &encoded); - VERIFY_EQ(encoded_size, encoded.size()); - if (!expected_huffman.empty() || plain.empty()) { - VERIFY_EQ(encoded, expected_huffman); - } - input_bytes_expected_ = encoded.size(); - auto validator = [plain, this]() -> AssertionResult { - VERIFY_EQ(output_buffer_.size(), plain.size()); - VERIFY_EQ(output_buffer_, plain); - return AssertionSuccess(); - }; - DecodeBuffer db(encoded); - bool return_non_zero_on_first = false; - return DecodeAndValidateSeveralWays(&db, return_non_zero_on_first, - ValidateDoneAndEmpty(validator)); - } - - AssertionResult TranscodeAndValidateSeveralWays(absl::string_view plain) { - return TranscodeAndValidateSeveralWays(plain, ""); - } - - std::string RandomAsciiNonControlString(int length) { - return Random().RandStringWithAlphabet(length, ascii_non_control_set_); - } - - std::string RandomBytes(int length) { return Random().RandString(length); } - - const std::string ascii_non_control_set_; - HpackHuffmanDecoder decoder_; - std::string output_buffer_; - size_t input_bytes_seen_; - size_t input_bytes_expected_; -}; - -TEST_F(HpackHuffmanTranscoderTest, RoundTripRandomAsciiNonControlString) { - for (size_t length = 0; length != 20; length++) { - const std::string s = RandomAsciiNonControlString(length); - ASSERT_TRUE(TranscodeAndValidateSeveralWays(s)) - << "Unable to decode:\n\n" - << quiche::QuicheTextUtils::HexDump(s) << "\n\noutput_buffer_:\n" - << quiche::QuicheTextUtils::HexDump(output_buffer_); - } -} - -TEST_F(HpackHuffmanTranscoderTest, RoundTripRandomBytes) { - for (size_t length = 0; length != 20; length++) { - const std::string s = RandomBytes(length); - ASSERT_TRUE(TranscodeAndValidateSeveralWays(s)) - << "Unable to decode:\n\n" - << quiche::QuicheTextUtils::HexDump(s) << "\n\noutput_buffer_:\n" - << quiche::QuicheTextUtils::HexDump(output_buffer_); - } -} - -// Two parameters: decoder choice, and the character to round-trip. -class HpackHuffmanTranscoderAdjacentCharTest - : public HpackHuffmanTranscoderTest, - public testing::WithParamInterface<int> { - protected: - HpackHuffmanTranscoderAdjacentCharTest() - : c_(static_cast<char>(GetParam())) {} - - const char c_; -}; - -INSTANTIATE_TEST_SUITE_P(HpackHuffmanTranscoderAdjacentCharTest, - HpackHuffmanTranscoderAdjacentCharTest, Range(0, 256)); - -// Test c_ adjacent to every other character, both before and after. -TEST_P(HpackHuffmanTranscoderAdjacentCharTest, RoundTripAdjacentChar) { - std::string s; - for (int a = 0; a < 256; ++a) { - s.push_back(static_cast<char>(a)); - s.push_back(c_); - s.push_back(static_cast<char>(a)); - } - ASSERT_TRUE(TranscodeAndValidateSeveralWays(s)); -} - -// Two parameters: character to repeat, number of repeats. -class HpackHuffmanTranscoderRepeatedCharTest - : public HpackHuffmanTranscoderTest, - public testing::WithParamInterface<std::tuple<int, int>> { - protected: - HpackHuffmanTranscoderRepeatedCharTest() - : c_(static_cast<char>(std::get<0>(GetParam()))), - length_(std::get<1>(GetParam())) {} - std::string MakeString() { return std::string(length_, c_); } - - private: - const char c_; - const size_t length_; -}; - -INSTANTIATE_TEST_SUITE_P(HpackHuffmanTranscoderRepeatedCharTest, - HpackHuffmanTranscoderRepeatedCharTest, - Combine(Range(0, 256), Values(1, 2, 3, 4, 8, 16, 32))); - -TEST_P(HpackHuffmanTranscoderRepeatedCharTest, RoundTripRepeatedChar) { - ASSERT_TRUE(TranscodeAndValidateSeveralWays(MakeString())); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.cc deleted file mode 100644 index a4e0d3c522a..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.cc +++ /dev/null @@ -1,572 +0,0 @@ -// Copyright (c) 2018 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/hpack/huffman/huffman_spec_tables.h" - -namespace http2 { - -// clang-format off -// static -const uint8_t HuffmanSpecTables::kCodeLengths[] = { - 13, 23, 28, 28, 28, 28, 28, 28, // 0 - 7 - 28, 24, 30, 28, 28, 30, 28, 28, // 8 - 15 - 28, 28, 28, 28, 28, 28, 30, 28, // 16 - 23 - 28, 28, 28, 28, 28, 28, 28, 28, // 24 - 31 - 6, 10, 10, 12, 13, 6, 8, 11, // 32 - 39 - 10, 10, 8, 11, 8, 6, 6, 6, // 40 - 47 - 5, 5, 5, 6, 6, 6, 6, 6, // 48 - 55 - 6, 6, 7, 8, 15, 6, 12, 10, // 56 - 63 - 13, 6, 7, 7, 7, 7, 7, 7, // 64 - 71 - 7, 7, 7, 7, 7, 7, 7, 7, // 72 - 79 - 7, 7, 7, 7, 7, 7, 7, 7, // 80 - 87 - 8, 7, 8, 13, 19, 13, 14, 6, // 88 - 95 - 15, 5, 6, 5, 6, 5, 6, 6, // 96 - 103 - 6, 5, 7, 7, 6, 6, 6, 5, // 104 - 111 - 6, 7, 6, 5, 5, 6, 7, 7, // 112 - 119 - 7, 7, 7, 15, 11, 14, 13, 28, // 120 - 127 - 20, 22, 20, 20, 22, 22, 22, 23, // 128 - 135 - 22, 23, 23, 23, 23, 23, 24, 23, // 136 - 143 - 24, 24, 22, 23, 24, 23, 23, 23, // 144 - 151 - 23, 21, 22, 23, 22, 23, 23, 24, // 152 - 159 - 22, 21, 20, 22, 22, 23, 23, 21, // 160 - 167 - 23, 22, 22, 24, 21, 22, 23, 23, // 168 - 175 - 21, 21, 22, 21, 23, 22, 23, 23, // 176 - 183 - 20, 22, 22, 22, 23, 22, 22, 23, // 184 - 191 - 26, 26, 20, 19, 22, 23, 22, 25, // 192 - 199 - 26, 26, 26, 27, 27, 26, 24, 25, // 200 - 207 - 19, 21, 26, 27, 27, 26, 27, 24, // 208 - 215 - 21, 21, 26, 26, 28, 27, 27, 27, // 216 - 223 - 20, 24, 20, 21, 22, 21, 21, 23, // 224 - 231 - 22, 22, 25, 25, 24, 24, 26, 23, // 232 - 239 - 26, 27, 26, 26, 27, 27, 27, 27, // 240 - 247 - 27, 28, 27, 27, 27, 27, 27, 26, // 248 - 255 - 30, // 256 -}; - -// The encoding of each symbol, left justified (as printed), which means that -// the first bit of the encoding is the high-order bit of the uint32. -// static -const uint32_t HuffmanSpecTables::kLeftCodes[] = { - 0b11111111110000000000000000000000, // 0x00 - 0b11111111111111111011000000000000, // 0x01 - 0b11111111111111111111111000100000, // 0x02 - 0b11111111111111111111111000110000, // 0x03 - 0b11111111111111111111111001000000, // 0x04 - 0b11111111111111111111111001010000, // 0x05 - 0b11111111111111111111111001100000, // 0x06 - 0b11111111111111111111111001110000, // 0x07 - 0b11111111111111111111111010000000, // 0x08 - 0b11111111111111111110101000000000, // 0x09 - 0b11111111111111111111111111110000, // 0x0a - 0b11111111111111111111111010010000, // 0x0b - 0b11111111111111111111111010100000, // 0x0c - 0b11111111111111111111111111110100, // 0x0d - 0b11111111111111111111111010110000, // 0x0e - 0b11111111111111111111111011000000, // 0x0f - 0b11111111111111111111111011010000, // 0x10 - 0b11111111111111111111111011100000, // 0x11 - 0b11111111111111111111111011110000, // 0x12 - 0b11111111111111111111111100000000, // 0x13 - 0b11111111111111111111111100010000, // 0x14 - 0b11111111111111111111111100100000, // 0x15 - 0b11111111111111111111111111111000, // 0x16 - 0b11111111111111111111111100110000, // 0x17 - 0b11111111111111111111111101000000, // 0x18 - 0b11111111111111111111111101010000, // 0x19 - 0b11111111111111111111111101100000, // 0x1a - 0b11111111111111111111111101110000, // 0x1b - 0b11111111111111111111111110000000, // 0x1c - 0b11111111111111111111111110010000, // 0x1d - 0b11111111111111111111111110100000, // 0x1e - 0b11111111111111111111111110110000, // 0x1f - 0b01010000000000000000000000000000, // 0x20 - 0b11111110000000000000000000000000, // '!' - 0b11111110010000000000000000000000, // '\"' - 0b11111111101000000000000000000000, // '#' - 0b11111111110010000000000000000000, // '$' - 0b01010100000000000000000000000000, // '%' - 0b11111000000000000000000000000000, // '&' - 0b11111111010000000000000000000000, // '\'' - 0b11111110100000000000000000000000, // '(' - 0b11111110110000000000000000000000, // ')' - 0b11111001000000000000000000000000, // '*' - 0b11111111011000000000000000000000, // '+' - 0b11111010000000000000000000000000, // ',' - 0b01011000000000000000000000000000, // '-' - 0b01011100000000000000000000000000, // '.' - 0b01100000000000000000000000000000, // '/' - 0b00000000000000000000000000000000, // '0' - 0b00001000000000000000000000000000, // '1' - 0b00010000000000000000000000000000, // '2' - 0b01100100000000000000000000000000, // '3' - 0b01101000000000000000000000000000, // '4' - 0b01101100000000000000000000000000, // '5' - 0b01110000000000000000000000000000, // '6' - 0b01110100000000000000000000000000, // '7' - 0b01111000000000000000000000000000, // '8' - 0b01111100000000000000000000000000, // '9' - 0b10111000000000000000000000000000, // ':' - 0b11111011000000000000000000000000, // ';' - 0b11111111111110000000000000000000, // '<' - 0b10000000000000000000000000000000, // '=' - 0b11111111101100000000000000000000, // '>' - 0b11111111000000000000000000000000, // '?' - 0b11111111110100000000000000000000, // '@' - 0b10000100000000000000000000000000, // 'A' - 0b10111010000000000000000000000000, // 'B' - 0b10111100000000000000000000000000, // 'C' - 0b10111110000000000000000000000000, // 'D' - 0b11000000000000000000000000000000, // 'E' - 0b11000010000000000000000000000000, // 'F' - 0b11000100000000000000000000000000, // 'G' - 0b11000110000000000000000000000000, // 'H' - 0b11001000000000000000000000000000, // 'I' - 0b11001010000000000000000000000000, // 'J' - 0b11001100000000000000000000000000, // 'K' - 0b11001110000000000000000000000000, // 'L' - 0b11010000000000000000000000000000, // 'M' - 0b11010010000000000000000000000000, // 'N' - 0b11010100000000000000000000000000, // 'O' - 0b11010110000000000000000000000000, // 'P' - 0b11011000000000000000000000000000, // 'Q' - 0b11011010000000000000000000000000, // 'R' - 0b11011100000000000000000000000000, // 'S' - 0b11011110000000000000000000000000, // 'T' - 0b11100000000000000000000000000000, // 'U' - 0b11100010000000000000000000000000, // 'V' - 0b11100100000000000000000000000000, // 'W' - 0b11111100000000000000000000000000, // 'X' - 0b11100110000000000000000000000000, // 'Y' - 0b11111101000000000000000000000000, // 'Z' - 0b11111111110110000000000000000000, // '[' - 0b11111111111111100000000000000000, // '\\' - 0b11111111111000000000000000000000, // ']' - 0b11111111111100000000000000000000, // '^' - 0b10001000000000000000000000000000, // '_' - 0b11111111111110100000000000000000, // '`' - 0b00011000000000000000000000000000, // 'a' - 0b10001100000000000000000000000000, // 'b' - 0b00100000000000000000000000000000, // 'c' - 0b10010000000000000000000000000000, // 'd' - 0b00101000000000000000000000000000, // 'e' - 0b10010100000000000000000000000000, // 'f' - 0b10011000000000000000000000000000, // 'g' - 0b10011100000000000000000000000000, // 'h' - 0b00110000000000000000000000000000, // 'i' - 0b11101000000000000000000000000000, // 'j' - 0b11101010000000000000000000000000, // 'k' - 0b10100000000000000000000000000000, // 'l' - 0b10100100000000000000000000000000, // 'm' - 0b10101000000000000000000000000000, // 'n' - 0b00111000000000000000000000000000, // 'o' - 0b10101100000000000000000000000000, // 'p' - 0b11101100000000000000000000000000, // 'q' - 0b10110000000000000000000000000000, // 'r' - 0b01000000000000000000000000000000, // 's' - 0b01001000000000000000000000000000, // 't' - 0b10110100000000000000000000000000, // 'u' - 0b11101110000000000000000000000000, // 'v' - 0b11110000000000000000000000000000, // 'w' - 0b11110010000000000000000000000000, // 'x' - 0b11110100000000000000000000000000, // 'y' - 0b11110110000000000000000000000000, // 'z' - 0b11111111111111000000000000000000, // '{' - 0b11111111100000000000000000000000, // '|' - 0b11111111111101000000000000000000, // '}' - 0b11111111111010000000000000000000, // '~' - 0b11111111111111111111111111000000, // 0x7f - 0b11111111111111100110000000000000, // 0x80 - 0b11111111111111110100100000000000, // 0x81 - 0b11111111111111100111000000000000, // 0x82 - 0b11111111111111101000000000000000, // 0x83 - 0b11111111111111110100110000000000, // 0x84 - 0b11111111111111110101000000000000, // 0x85 - 0b11111111111111110101010000000000, // 0x86 - 0b11111111111111111011001000000000, // 0x87 - 0b11111111111111110101100000000000, // 0x88 - 0b11111111111111111011010000000000, // 0x89 - 0b11111111111111111011011000000000, // 0x8a - 0b11111111111111111011100000000000, // 0x8b - 0b11111111111111111011101000000000, // 0x8c - 0b11111111111111111011110000000000, // 0x8d - 0b11111111111111111110101100000000, // 0x8e - 0b11111111111111111011111000000000, // 0x8f - 0b11111111111111111110110000000000, // 0x90 - 0b11111111111111111110110100000000, // 0x91 - 0b11111111111111110101110000000000, // 0x92 - 0b11111111111111111100000000000000, // 0x93 - 0b11111111111111111110111000000000, // 0x94 - 0b11111111111111111100001000000000, // 0x95 - 0b11111111111111111100010000000000, // 0x96 - 0b11111111111111111100011000000000, // 0x97 - 0b11111111111111111100100000000000, // 0x98 - 0b11111111111111101110000000000000, // 0x99 - 0b11111111111111110110000000000000, // 0x9a - 0b11111111111111111100101000000000, // 0x9b - 0b11111111111111110110010000000000, // 0x9c - 0b11111111111111111100110000000000, // 0x9d - 0b11111111111111111100111000000000, // 0x9e - 0b11111111111111111110111100000000, // 0x9f - 0b11111111111111110110100000000000, // 0xa0 - 0b11111111111111101110100000000000, // 0xa1 - 0b11111111111111101001000000000000, // 0xa2 - 0b11111111111111110110110000000000, // 0xa3 - 0b11111111111111110111000000000000, // 0xa4 - 0b11111111111111111101000000000000, // 0xa5 - 0b11111111111111111101001000000000, // 0xa6 - 0b11111111111111101111000000000000, // 0xa7 - 0b11111111111111111101010000000000, // 0xa8 - 0b11111111111111110111010000000000, // 0xa9 - 0b11111111111111110111100000000000, // 0xaa - 0b11111111111111111111000000000000, // 0xab - 0b11111111111111101111100000000000, // 0xac - 0b11111111111111110111110000000000, // 0xad - 0b11111111111111111101011000000000, // 0xae - 0b11111111111111111101100000000000, // 0xaf - 0b11111111111111110000000000000000, // 0xb0 - 0b11111111111111110000100000000000, // 0xb1 - 0b11111111111111111000000000000000, // 0xb2 - 0b11111111111111110001000000000000, // 0xb3 - 0b11111111111111111101101000000000, // 0xb4 - 0b11111111111111111000010000000000, // 0xb5 - 0b11111111111111111101110000000000, // 0xb6 - 0b11111111111111111101111000000000, // 0xb7 - 0b11111111111111101010000000000000, // 0xb8 - 0b11111111111111111000100000000000, // 0xb9 - 0b11111111111111111000110000000000, // 0xba - 0b11111111111111111001000000000000, // 0xbb - 0b11111111111111111110000000000000, // 0xbc - 0b11111111111111111001010000000000, // 0xbd - 0b11111111111111111001100000000000, // 0xbe - 0b11111111111111111110001000000000, // 0xbf - 0b11111111111111111111100000000000, // 0xc0 - 0b11111111111111111111100001000000, // 0xc1 - 0b11111111111111101011000000000000, // 0xc2 - 0b11111111111111100010000000000000, // 0xc3 - 0b11111111111111111001110000000000, // 0xc4 - 0b11111111111111111110010000000000, // 0xc5 - 0b11111111111111111010000000000000, // 0xc6 - 0b11111111111111111111011000000000, // 0xc7 - 0b11111111111111111111100010000000, // 0xc8 - 0b11111111111111111111100011000000, // 0xc9 - 0b11111111111111111111100100000000, // 0xca - 0b11111111111111111111101111000000, // 0xcb - 0b11111111111111111111101111100000, // 0xcc - 0b11111111111111111111100101000000, // 0xcd - 0b11111111111111111111000100000000, // 0xce - 0b11111111111111111111011010000000, // 0xcf - 0b11111111111111100100000000000000, // 0xd0 - 0b11111111111111110001100000000000, // 0xd1 - 0b11111111111111111111100110000000, // 0xd2 - 0b11111111111111111111110000000000, // 0xd3 - 0b11111111111111111111110000100000, // 0xd4 - 0b11111111111111111111100111000000, // 0xd5 - 0b11111111111111111111110001000000, // 0xd6 - 0b11111111111111111111001000000000, // 0xd7 - 0b11111111111111110010000000000000, // 0xd8 - 0b11111111111111110010100000000000, // 0xd9 - 0b11111111111111111111101000000000, // 0xda - 0b11111111111111111111101001000000, // 0xdb - 0b11111111111111111111111111010000, // 0xdc - 0b11111111111111111111110001100000, // 0xdd - 0b11111111111111111111110010000000, // 0xde - 0b11111111111111111111110010100000, // 0xdf - 0b11111111111111101100000000000000, // 0xe0 - 0b11111111111111111111001100000000, // 0xe1 - 0b11111111111111101101000000000000, // 0xe2 - 0b11111111111111110011000000000000, // 0xe3 - 0b11111111111111111010010000000000, // 0xe4 - 0b11111111111111110011100000000000, // 0xe5 - 0b11111111111111110100000000000000, // 0xe6 - 0b11111111111111111110011000000000, // 0xe7 - 0b11111111111111111010100000000000, // 0xe8 - 0b11111111111111111010110000000000, // 0xe9 - 0b11111111111111111111011100000000, // 0xea - 0b11111111111111111111011110000000, // 0xeb - 0b11111111111111111111010000000000, // 0xec - 0b11111111111111111111010100000000, // 0xed - 0b11111111111111111111101010000000, // 0xee - 0b11111111111111111110100000000000, // 0xef - 0b11111111111111111111101011000000, // 0xf0 - 0b11111111111111111111110011000000, // 0xf1 - 0b11111111111111111111101100000000, // 0xf2 - 0b11111111111111111111101101000000, // 0xf3 - 0b11111111111111111111110011100000, // 0xf4 - 0b11111111111111111111110100000000, // 0xf5 - 0b11111111111111111111110100100000, // 0xf6 - 0b11111111111111111111110101000000, // 0xf7 - 0b11111111111111111111110101100000, // 0xf8 - 0b11111111111111111111111111100000, // 0xf9 - 0b11111111111111111111110110000000, // 0xfa - 0b11111111111111111111110110100000, // 0xfb - 0b11111111111111111111110111000000, // 0xfc - 0b11111111111111111111110111100000, // 0xfd - 0b11111111111111111111111000000000, // 0xfe - 0b11111111111111111111101110000000, // 0xff - 0b11111111111111111111111111111100, // 0x100 -}; - -// static -const uint32_t HuffmanSpecTables::kRightCodes[] = { - 0b00000000000000000001111111111000, // 0x00 - 0b00000000011111111111111111011000, // 0x01 - 0b00001111111111111111111111100010, // 0x02 - 0b00001111111111111111111111100011, // 0x03 - 0b00001111111111111111111111100100, // 0x04 - 0b00001111111111111111111111100101, // 0x05 - 0b00001111111111111111111111100110, // 0x06 - 0b00001111111111111111111111100111, // 0x07 - 0b00001111111111111111111111101000, // 0x08 - 0b00000000111111111111111111101010, // 0x09 - 0b00111111111111111111111111111100, // 0x0a - 0b00001111111111111111111111101001, // 0x0b - 0b00001111111111111111111111101010, // 0x0c - 0b00111111111111111111111111111101, // 0x0d - 0b00001111111111111111111111101011, // 0x0e - 0b00001111111111111111111111101100, // 0x0f - 0b00001111111111111111111111101101, // 0x10 - 0b00001111111111111111111111101110, // 0x11 - 0b00001111111111111111111111101111, // 0x12 - 0b00001111111111111111111111110000, // 0x13 - 0b00001111111111111111111111110001, // 0x14 - 0b00001111111111111111111111110010, // 0x15 - 0b00111111111111111111111111111110, // 0x16 - 0b00001111111111111111111111110011, // 0x17 - 0b00001111111111111111111111110100, // 0x18 - 0b00001111111111111111111111110101, // 0x19 - 0b00001111111111111111111111110110, // 0x1a - 0b00001111111111111111111111110111, // 0x1b - 0b00001111111111111111111111111000, // 0x1c - 0b00001111111111111111111111111001, // 0x1d - 0b00001111111111111111111111111010, // 0x1e - 0b00001111111111111111111111111011, // 0x1f - 0b00000000000000000000000000010100, // 0x20 - 0b00000000000000000000001111111000, // '!' - 0b00000000000000000000001111111001, // '\"' - 0b00000000000000000000111111111010, // '#' - 0b00000000000000000001111111111001, // '$' - 0b00000000000000000000000000010101, // '%' - 0b00000000000000000000000011111000, // '&' - 0b00000000000000000000011111111010, // '\'' - 0b00000000000000000000001111111010, // '(' - 0b00000000000000000000001111111011, // ')' - 0b00000000000000000000000011111001, // '*' - 0b00000000000000000000011111111011, // '+' - 0b00000000000000000000000011111010, // ',' - 0b00000000000000000000000000010110, // '-' - 0b00000000000000000000000000010111, // '.' - 0b00000000000000000000000000011000, // '/' - 0b00000000000000000000000000000000, // '0' - 0b00000000000000000000000000000001, // '1' - 0b00000000000000000000000000000010, // '2' - 0b00000000000000000000000000011001, // '3' - 0b00000000000000000000000000011010, // '4' - 0b00000000000000000000000000011011, // '5' - 0b00000000000000000000000000011100, // '6' - 0b00000000000000000000000000011101, // '7' - 0b00000000000000000000000000011110, // '8' - 0b00000000000000000000000000011111, // '9' - 0b00000000000000000000000001011100, // ':' - 0b00000000000000000000000011111011, // ';' - 0b00000000000000000111111111111100, // '<' - 0b00000000000000000000000000100000, // '=' - 0b00000000000000000000111111111011, // '>' - 0b00000000000000000000001111111100, // '?' - 0b00000000000000000001111111111010, // '@' - 0b00000000000000000000000000100001, // 'A' - 0b00000000000000000000000001011101, // 'B' - 0b00000000000000000000000001011110, // 'C' - 0b00000000000000000000000001011111, // 'D' - 0b00000000000000000000000001100000, // 'E' - 0b00000000000000000000000001100001, // 'F' - 0b00000000000000000000000001100010, // 'G' - 0b00000000000000000000000001100011, // 'H' - 0b00000000000000000000000001100100, // 'I' - 0b00000000000000000000000001100101, // 'J' - 0b00000000000000000000000001100110, // 'K' - 0b00000000000000000000000001100111, // 'L' - 0b00000000000000000000000001101000, // 'M' - 0b00000000000000000000000001101001, // 'N' - 0b00000000000000000000000001101010, // 'O' - 0b00000000000000000000000001101011, // 'P' - 0b00000000000000000000000001101100, // 'Q' - 0b00000000000000000000000001101101, // 'R' - 0b00000000000000000000000001101110, // 'S' - 0b00000000000000000000000001101111, // 'T' - 0b00000000000000000000000001110000, // 'U' - 0b00000000000000000000000001110001, // 'V' - 0b00000000000000000000000001110010, // 'W' - 0b00000000000000000000000011111100, // 'X' - 0b00000000000000000000000001110011, // 'Y' - 0b00000000000000000000000011111101, // 'Z' - 0b00000000000000000001111111111011, // '[' - 0b00000000000001111111111111110000, // '\\' - 0b00000000000000000001111111111100, // ']' - 0b00000000000000000011111111111100, // '^' - 0b00000000000000000000000000100010, // '_' - 0b00000000000000000111111111111101, // '`' - 0b00000000000000000000000000000011, // 'a' - 0b00000000000000000000000000100011, // 'b' - 0b00000000000000000000000000000100, // 'c' - 0b00000000000000000000000000100100, // 'd' - 0b00000000000000000000000000000101, // 'e' - 0b00000000000000000000000000100101, // 'f' - 0b00000000000000000000000000100110, // 'g' - 0b00000000000000000000000000100111, // 'h' - 0b00000000000000000000000000000110, // 'i' - 0b00000000000000000000000001110100, // 'j' - 0b00000000000000000000000001110101, // 'k' - 0b00000000000000000000000000101000, // 'l' - 0b00000000000000000000000000101001, // 'm' - 0b00000000000000000000000000101010, // 'n' - 0b00000000000000000000000000000111, // 'o' - 0b00000000000000000000000000101011, // 'p' - 0b00000000000000000000000001110110, // 'q' - 0b00000000000000000000000000101100, // 'r' - 0b00000000000000000000000000001000, // 's' - 0b00000000000000000000000000001001, // 't' - 0b00000000000000000000000000101101, // 'u' - 0b00000000000000000000000001110111, // 'v' - 0b00000000000000000000000001111000, // 'w' - 0b00000000000000000000000001111001, // 'x' - 0b00000000000000000000000001111010, // 'y' - 0b00000000000000000000000001111011, // 'z' - 0b00000000000000000111111111111110, // '{' - 0b00000000000000000000011111111100, // '|' - 0b00000000000000000011111111111101, // '}' - 0b00000000000000000001111111111101, // '~' - 0b00001111111111111111111111111100, // 0x7f - 0b00000000000011111111111111100110, // 0x80 - 0b00000000001111111111111111010010, // 0x81 - 0b00000000000011111111111111100111, // 0x82 - 0b00000000000011111111111111101000, // 0x83 - 0b00000000001111111111111111010011, // 0x84 - 0b00000000001111111111111111010100, // 0x85 - 0b00000000001111111111111111010101, // 0x86 - 0b00000000011111111111111111011001, // 0x87 - 0b00000000001111111111111111010110, // 0x88 - 0b00000000011111111111111111011010, // 0x89 - 0b00000000011111111111111111011011, // 0x8a - 0b00000000011111111111111111011100, // 0x8b - 0b00000000011111111111111111011101, // 0x8c - 0b00000000011111111111111111011110, // 0x8d - 0b00000000111111111111111111101011, // 0x8e - 0b00000000011111111111111111011111, // 0x8f - 0b00000000111111111111111111101100, // 0x90 - 0b00000000111111111111111111101101, // 0x91 - 0b00000000001111111111111111010111, // 0x92 - 0b00000000011111111111111111100000, // 0x93 - 0b00000000111111111111111111101110, // 0x94 - 0b00000000011111111111111111100001, // 0x95 - 0b00000000011111111111111111100010, // 0x96 - 0b00000000011111111111111111100011, // 0x97 - 0b00000000011111111111111111100100, // 0x98 - 0b00000000000111111111111111011100, // 0x99 - 0b00000000001111111111111111011000, // 0x9a - 0b00000000011111111111111111100101, // 0x9b - 0b00000000001111111111111111011001, // 0x9c - 0b00000000011111111111111111100110, // 0x9d - 0b00000000011111111111111111100111, // 0x9e - 0b00000000111111111111111111101111, // 0x9f - 0b00000000001111111111111111011010, // 0xa0 - 0b00000000000111111111111111011101, // 0xa1 - 0b00000000000011111111111111101001, // 0xa2 - 0b00000000001111111111111111011011, // 0xa3 - 0b00000000001111111111111111011100, // 0xa4 - 0b00000000011111111111111111101000, // 0xa5 - 0b00000000011111111111111111101001, // 0xa6 - 0b00000000000111111111111111011110, // 0xa7 - 0b00000000011111111111111111101010, // 0xa8 - 0b00000000001111111111111111011101, // 0xa9 - 0b00000000001111111111111111011110, // 0xaa - 0b00000000111111111111111111110000, // 0xab - 0b00000000000111111111111111011111, // 0xac - 0b00000000001111111111111111011111, // 0xad - 0b00000000011111111111111111101011, // 0xae - 0b00000000011111111111111111101100, // 0xaf - 0b00000000000111111111111111100000, // 0xb0 - 0b00000000000111111111111111100001, // 0xb1 - 0b00000000001111111111111111100000, // 0xb2 - 0b00000000000111111111111111100010, // 0xb3 - 0b00000000011111111111111111101101, // 0xb4 - 0b00000000001111111111111111100001, // 0xb5 - 0b00000000011111111111111111101110, // 0xb6 - 0b00000000011111111111111111101111, // 0xb7 - 0b00000000000011111111111111101010, // 0xb8 - 0b00000000001111111111111111100010, // 0xb9 - 0b00000000001111111111111111100011, // 0xba - 0b00000000001111111111111111100100, // 0xbb - 0b00000000011111111111111111110000, // 0xbc - 0b00000000001111111111111111100101, // 0xbd - 0b00000000001111111111111111100110, // 0xbe - 0b00000000011111111111111111110001, // 0xbf - 0b00000011111111111111111111100000, // 0xc0 - 0b00000011111111111111111111100001, // 0xc1 - 0b00000000000011111111111111101011, // 0xc2 - 0b00000000000001111111111111110001, // 0xc3 - 0b00000000001111111111111111100111, // 0xc4 - 0b00000000011111111111111111110010, // 0xc5 - 0b00000000001111111111111111101000, // 0xc6 - 0b00000001111111111111111111101100, // 0xc7 - 0b00000011111111111111111111100010, // 0xc8 - 0b00000011111111111111111111100011, // 0xc9 - 0b00000011111111111111111111100100, // 0xca - 0b00000111111111111111111111011110, // 0xcb - 0b00000111111111111111111111011111, // 0xcc - 0b00000011111111111111111111100101, // 0xcd - 0b00000000111111111111111111110001, // 0xce - 0b00000001111111111111111111101101, // 0xcf - 0b00000000000001111111111111110010, // 0xd0 - 0b00000000000111111111111111100011, // 0xd1 - 0b00000011111111111111111111100110, // 0xd2 - 0b00000111111111111111111111100000, // 0xd3 - 0b00000111111111111111111111100001, // 0xd4 - 0b00000011111111111111111111100111, // 0xd5 - 0b00000111111111111111111111100010, // 0xd6 - 0b00000000111111111111111111110010, // 0xd7 - 0b00000000000111111111111111100100, // 0xd8 - 0b00000000000111111111111111100101, // 0xd9 - 0b00000011111111111111111111101000, // 0xda - 0b00000011111111111111111111101001, // 0xdb - 0b00001111111111111111111111111101, // 0xdc - 0b00000111111111111111111111100011, // 0xdd - 0b00000111111111111111111111100100, // 0xde - 0b00000111111111111111111111100101, // 0xdf - 0b00000000000011111111111111101100, // 0xe0 - 0b00000000111111111111111111110011, // 0xe1 - 0b00000000000011111111111111101101, // 0xe2 - 0b00000000000111111111111111100110, // 0xe3 - 0b00000000001111111111111111101001, // 0xe4 - 0b00000000000111111111111111100111, // 0xe5 - 0b00000000000111111111111111101000, // 0xe6 - 0b00000000011111111111111111110011, // 0xe7 - 0b00000000001111111111111111101010, // 0xe8 - 0b00000000001111111111111111101011, // 0xe9 - 0b00000001111111111111111111101110, // 0xea - 0b00000001111111111111111111101111, // 0xeb - 0b00000000111111111111111111110100, // 0xec - 0b00000000111111111111111111110101, // 0xed - 0b00000011111111111111111111101010, // 0xee - 0b00000000011111111111111111110100, // 0xef - 0b00000011111111111111111111101011, // 0xf0 - 0b00000111111111111111111111100110, // 0xf1 - 0b00000011111111111111111111101100, // 0xf2 - 0b00000011111111111111111111101101, // 0xf3 - 0b00000111111111111111111111100111, // 0xf4 - 0b00000111111111111111111111101000, // 0xf5 - 0b00000111111111111111111111101001, // 0xf6 - 0b00000111111111111111111111101010, // 0xf7 - 0b00000111111111111111111111101011, // 0xf8 - 0b00001111111111111111111111111110, // 0xf9 - 0b00000111111111111111111111101100, // 0xfa - 0b00000111111111111111111111101101, // 0xfb - 0b00000111111111111111111111101110, // 0xfc - 0b00000111111111111111111111101111, // 0xfd - 0b00000111111111111111111111110000, // 0xfe - 0b00000011111111111111111111101110, // 0xff - 0b00111111111111111111111111111111, // 0x100 -}; -// clang-format off - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.h b/chromium/net/third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.h deleted file mode 100644 index d1b144b1358..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2018 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_HPACK_HUFFMAN_HUFFMAN_SPEC_TABLES_H_ -#define QUICHE_HTTP2_HPACK_HUFFMAN_HUFFMAN_SPEC_TABLES_H_ - -// Tables describing the Huffman encoding of bytes as specified by RFC7541. - -#include <cstdint> - -namespace http2 { - -struct HuffmanSpecTables { - // Number of bits in the encoding of each symbol (byte). - static const uint8_t kCodeLengths[257]; - - // The encoding of each symbol, right justified (as printed), which means that - // the last bit of the encoding is the low-order bit of the uint32. - static const uint32_t kRightCodes[257]; - - // The encoding of each symbol, left justified (as printed), which means that - // the first bit of the encoding is the high-order bit of the uint32. - static const uint32_t kLeftCodes[257]; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_HUFFMAN_HUFFMAN_SPEC_TABLES_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc deleted file mode 100644 index 3dbda955f0d..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.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/hpack/tools/hpack_block_builder.h" - -#include "http2/hpack/varint/hpack_varint_encoder.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -void HpackBlockBuilder::AppendHighBitsAndVarint(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint) { - EXPECT_LE(3, prefix_length); - EXPECT_LE(prefix_length, 8); - - HpackVarintEncoder::Encode(high_bits, prefix_length, varint, &buffer_); -} - -void HpackBlockBuilder::AppendEntryTypeAndVarint(HpackEntryType entry_type, - uint64_t varint) { - uint8_t high_bits; - uint8_t prefix_length; // Bits of the varint prefix in the first byte. - switch (entry_type) { - case HpackEntryType::kIndexedHeader: - high_bits = 0x80; - prefix_length = 7; - break; - case HpackEntryType::kDynamicTableSizeUpdate: - high_bits = 0x20; - prefix_length = 5; - break; - case HpackEntryType::kIndexedLiteralHeader: - high_bits = 0x40; - prefix_length = 6; - break; - case HpackEntryType::kUnindexedLiteralHeader: - high_bits = 0x00; - prefix_length = 4; - break; - case HpackEntryType::kNeverIndexedLiteralHeader: - high_bits = 0x10; - prefix_length = 4; - break; - default: - HTTP2_BUG(http2_bug_110_1) << "Unreached, entry_type=" << entry_type; - high_bits = 0; - prefix_length = 0; - break; - } - AppendHighBitsAndVarint(high_bits, prefix_length, varint); -} - -void HpackBlockBuilder::AppendString(bool is_huffman_encoded, - absl::string_view str) { - uint8_t high_bits = is_huffman_encoded ? 0x80 : 0; - uint8_t prefix_length = 7; - AppendHighBitsAndVarint(high_bits, prefix_length, str.size()); - buffer_.append(str.data(), str.size()); -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h deleted file mode 100644 index 079f82384f9..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h +++ /dev/null @@ -1,97 +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_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ -#define QUICHE_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ - -// HpackBlockBuilder builds wire-format HPACK blocks (or fragments thereof) -// from components. - -// Supports very large varints to enable tests to create HPACK blocks with -// values that the decoder should reject. For now, this is only intended for -// use in tests, and thus has EXPECT* in the code. If desired to use it in an -// encoder, it will need optimization work, especially w.r.t memory mgmt, and -// the EXPECT* will need to be removed or replaced with QUICHE_DCHECKs. And of -// course the support for very large varints will not be needed in production -// code. - -#include <stddef.h> - -#include <cstdint> -#include <string> - -#include "absl/strings/string_view.h" -#include "http2/hpack/http2_hpack_constants.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { - -class HpackBlockBuilder { - public: - explicit HpackBlockBuilder(absl::string_view initial_contents) - : buffer_(initial_contents.data(), initial_contents.size()) {} - HpackBlockBuilder() {} - ~HpackBlockBuilder() {} - - size_t size() const { return buffer_.size(); } - const std::string& buffer() const { return buffer_; } - - //---------------------------------------------------------------------------- - // Methods for appending a valid HPACK entry. - - void AppendIndexedHeader(uint64_t index) { - AppendEntryTypeAndVarint(HpackEntryType::kIndexedHeader, index); - } - - void AppendDynamicTableSizeUpdate(uint64_t size) { - AppendEntryTypeAndVarint(HpackEntryType::kDynamicTableSizeUpdate, size); - } - - void AppendNameIndexAndLiteralValue(HpackEntryType entry_type, - uint64_t name_index, - bool value_is_huffman_encoded, - absl::string_view value) { - // name_index==0 would indicate that the entry includes a literal name. - // Call AppendLiteralNameAndValue in that case. - EXPECT_NE(0u, name_index); - AppendEntryTypeAndVarint(entry_type, name_index); - AppendString(value_is_huffman_encoded, value); - } - - void AppendLiteralNameAndValue(HpackEntryType entry_type, - bool name_is_huffman_encoded, - absl::string_view name, - bool value_is_huffman_encoded, - absl::string_view value) { - AppendEntryTypeAndVarint(entry_type, 0); - AppendString(name_is_huffman_encoded, name); - AppendString(value_is_huffman_encoded, value); - } - - //---------------------------------------------------------------------------- - // Primitive methods that are not guaranteed to write a valid HPACK entry. - - // Appends a varint, with the specified high_bits above the prefix of the - // varint. - void AppendHighBitsAndVarint(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint); - - // Append the start of an HPACK entry for the specified type, with the - // specified varint. - void AppendEntryTypeAndVarint(HpackEntryType entry_type, uint64_t varint); - - // Append a header string (i.e. a header name or value) in HPACK format. - // Does NOT perform Huffman encoding. - void AppendString(bool is_huffman_encoded, absl::string_view str); - - private: - std::string buffer_; -}; - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc deleted file mode 100644 index b292c4b3767..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc +++ /dev/null @@ -1,169 +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/hpack/tools/hpack_block_builder.h" - -#include "absl/strings/escaping.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -namespace { -const bool kUncompressed = false; -const bool kCompressed = true; - -// TODO(jamessynge): Once static table code is checked in, switch to using -// constants from there. -const uint32_t kStaticTableMethodGET = 2; -const uint32_t kStaticTablePathSlash = 4; -const uint32_t kStaticTableSchemeHttp = 6; - -// Tests of encoding per the RFC. See: -// http://httpwg.org/specs/rfc7541.html#header.field.representation.examples -// The expected values have been copied from the RFC. -TEST(HpackBlockBuilderTest, ExamplesFromSpecC2) { - { - HpackBlockBuilder b; - b.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, - kUncompressed, "custom-key", kUncompressed, - "custom-header"); - EXPECT_EQ(26u, b.size()); - - const char kExpected[] = - "\x40" // == Literal indexed == - "\x0a" // Name length (10) - "custom-key" // Name - "\x0d" // Value length (13) - "custom-header"; // Value - EXPECT_EQ(kExpected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendNameIndexAndLiteralValue(HpackEntryType::kUnindexedLiteralHeader, 4, - kUncompressed, "/sample/path"); - EXPECT_EQ(14u, b.size()); - - const char kExpected[] = - "\x04" // == Literal unindexed, name index 0x04 == - "\x0c" // Value length (12) - "/sample/path"; // Value - EXPECT_EQ(kExpected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, - kUncompressed, "password", kUncompressed, - "secret"); - EXPECT_EQ(17u, b.size()); - - const char kExpected[] = - "\x10" // == Literal never indexed == - "\x08" // Name length (8) - "password" // Name - "\x06" // Value length (6) - "secret"; // Value - EXPECT_EQ(kExpected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendIndexedHeader(2); - EXPECT_EQ(1u, b.size()); - - const char kExpected[] = "\x82"; // == Indexed (2) == - EXPECT_EQ(kExpected, b.buffer()); - } -} - -// Tests of encoding per the RFC. See: -// http://httpwg.org/specs/rfc7541.html#request.examples.without.huffman.coding -TEST(HpackBlockBuilderTest, ExamplesFromSpecC3) { - { - // Header block to encode: - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com - HpackBlockBuilder b; - b.AppendIndexedHeader(2); // :method: GET - b.AppendIndexedHeader(6); // :scheme: http - b.AppendIndexedHeader(4); // :path: / - b.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 1, - kUncompressed, "www.example.com"); - EXPECT_EQ(20u, b.size()); - - // Hex dump of encoded data (copied from RFC): - // 0x0000: 8286 8441 0f77 7777 2e65 7861 6d70 6c65 ...A.www.example - // 0x0010: 2e63 6f6d .com - - const std::string expected = - absl::HexStringToBytes("828684410f7777772e6578616d706c652e636f6d"); - EXPECT_EQ(expected, b.buffer()); - } -} - -// Tests of encoding per the RFC. See: -// http://httpwg.org/specs/rfc7541.html#request.examples.with.huffman.coding -TEST(HpackBlockBuilderTest, ExamplesFromSpecC4) { - { - // Header block to encode: - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com (Huffman encoded) - HpackBlockBuilder b; - b.AppendIndexedHeader(kStaticTableMethodGET); - b.AppendIndexedHeader(kStaticTableSchemeHttp); - b.AppendIndexedHeader(kStaticTablePathSlash); - const char kHuffmanWwwExampleCom[] = {'\xf1', '\xe3', '\xc2', '\xe5', - '\xf2', '\x3a', '\x6b', '\xa0', - '\xab', '\x90', '\xf4', '\xff'}; - b.AppendNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, 1, kCompressed, - absl::string_view(kHuffmanWwwExampleCom, sizeof kHuffmanWwwExampleCom)); - EXPECT_EQ(17u, b.size()); - - // Hex dump of encoded data (copied from RFC): - // 0x0000: 8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ...A......:k.... - // 0x0010: ff . - - const std::string expected = - absl::HexStringToBytes("828684418cf1e3c2e5f23a6ba0ab90f4ff"); - EXPECT_EQ(expected, b.buffer()); - } -} - -TEST(HpackBlockBuilderTest, DynamicTableSizeUpdate) { - { - HpackBlockBuilder b; - b.AppendDynamicTableSizeUpdate(0); - EXPECT_EQ(1u, b.size()); - - const char kData[] = {'\x20'}; - absl::string_view expected(kData, sizeof kData); - EXPECT_EQ(expected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendDynamicTableSizeUpdate(4096); // The default size. - EXPECT_EQ(3u, b.size()); - - const char kData[] = {'\x3f', '\xe1', '\x1f'}; - absl::string_view expected(kData, sizeof kData); - EXPECT_EQ(expected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendDynamicTableSizeUpdate(1000000000000); // A very large value. - EXPECT_EQ(7u, b.size()); - - const char kData[] = {'\x3f', '\xe1', '\x9f', '\x94', - '\xa5', '\x8d', '\x1d'}; - absl::string_view expected(kData, sizeof kData); - EXPECT_EQ(expected, b.buffer()); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc deleted file mode 100644 index 64255b1ef2d..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.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/hpack/tools/hpack_example.h" - -#include <ctype.h> - -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "http2/platform/api/http2_bug_tracker.h" -#include "http2/platform/api/http2_logging.h" - -namespace http2 { -namespace test { -namespace { - -void HpackExampleToStringOrDie(absl::string_view example, std::string* output) { - while (!example.empty()) { - const char c0 = example[0]; - if (isxdigit(c0)) { - QUICHE_CHECK_GT(example.size(), 1u) << "Truncated hex byte?"; - const char c1 = example[1]; - QUICHE_CHECK(isxdigit(c1)) << "Found half a byte?"; - *output += absl::HexStringToBytes(example.substr(0, 2)); - example.remove_prefix(2); - continue; - } - if (isspace(c0)) { - example.remove_prefix(1); - continue; - } - if (!example.empty() && example[0] == '|') { - // Start of a comment. Skip to end of line or of input. - auto pos = example.find('\n'); - if (pos == absl::string_view::npos) { - // End of input. - break; - } - example.remove_prefix(pos + 1); - continue; - } - HTTP2_BUG(http2_bug_107_1) - << "Can't parse byte " << static_cast<int>(c0) - << absl::StrCat(" (0x", absl::Hex(c0), ")") << "\nExample: " << example; - } - QUICHE_CHECK_LT(0u, output->size()) << "Example is empty."; -} - -} // namespace - -std::string HpackExampleToStringOrDie(absl::string_view example) { - std::string output; - HpackExampleToStringOrDie(example, &output); - return output; -} - -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.h b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.h deleted file mode 100644 index de203cccbde..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.h +++ /dev/null @@ -1,32 +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_HPACK_TOOLS_HPACK_EXAMPLE_H_ -#define QUICHE_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_ - -#include <string> - -#include "absl/strings/string_view.h" - -// Parses HPACK examples in the format seen in the HPACK specification, -// RFC 7541. For example: -// -// 10 | == Literal never indexed == -// 08 | Literal name (len = 8) -// 7061 7373 776f 7264 | password -// 06 | Literal value (len = 6) -// 7365 6372 6574 | secret -// | -> password: secret -// -// (excluding the leading "//"). - -namespace http2 { -namespace test { - -std::string HpackExampleToStringOrDie(absl::string_view example); - -} // namespace test -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc deleted file mode 100644 index a9e6e74cb07..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc +++ /dev/null @@ -1,143 +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/hpack/varint/hpack_varint_decoder.h" - -#include "absl/strings/str_cat.h" - -namespace http2 { - -DecodeStatus HpackVarintDecoder::Start(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db) { - QUICHE_DCHECK_LE(3u, prefix_length); - QUICHE_DCHECK_LE(prefix_length, 8u); - - // |prefix_mask| defines the sequence of low-order bits of the first byte - // that encode the prefix of the value. It is also the marker in those bits - // of the first byte indicating that at least one extension byte is needed. - const uint8_t prefix_mask = (1 << prefix_length) - 1; - - // Ignore the bits that aren't a part of the prefix of the varint. - value_ = prefix_value & prefix_mask; - - if (value_ < prefix_mask) { - MarkDone(); - return DecodeStatus::kDecodeDone; - } - - offset_ = 0; - return Resume(db); -} - -DecodeStatus HpackVarintDecoder::StartExtended(uint8_t prefix_length, - DecodeBuffer* db) { - QUICHE_DCHECK_LE(3u, prefix_length); - QUICHE_DCHECK_LE(prefix_length, 8u); - - value_ = (1 << prefix_length) - 1; - offset_ = 0; - return Resume(db); -} - -DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) { - // There can be at most 10 continuation bytes. Offset is zero for the - // first one and increases by 7 for each subsequent one. - const uint8_t kMaxOffset = 63; - CheckNotDone(); - - // Process most extension bytes without the need for overflow checking. - while (offset_ < kMaxOffset) { - if (db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - - uint8_t byte = db->DecodeUInt8(); - uint64_t summand = byte & 0x7f; - - // Shifting a 7 bit value to the left by at most 56 places can never - // overflow on uint64_t. - QUICHE_DCHECK_LE(offset_, 56); - QUICHE_DCHECK_LE(summand, std::numeric_limits<uint64_t>::max() >> offset_); - - summand <<= offset_; - - // At this point, - // |value_| is at most (2^prefix_length - 1) + (2^49 - 1), and - // |summand| is at most 255 << 56 (which is smaller than 2^63), - // so adding them can never overflow on uint64_t. - QUICHE_DCHECK_LE(value_, std::numeric_limits<uint64_t>::max() - summand); - - value_ += summand; - - // Decoding ends if continuation flag is not set. - if ((byte & 0x80) == 0) { - MarkDone(); - return DecodeStatus::kDecodeDone; - } - - offset_ += 7; - } - - if (db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - - QUICHE_DCHECK_EQ(kMaxOffset, offset_); - - uint8_t byte = db->DecodeUInt8(); - // No more extension bytes are allowed after this. - if ((byte & 0x80) == 0) { - uint64_t summand = byte & 0x7f; - // Check for overflow in left shift. - if (summand <= std::numeric_limits<uint64_t>::max() >> offset_) { - summand <<= offset_; - // Check for overflow in addition. - if (value_ <= std::numeric_limits<uint64_t>::max() - summand) { - value_ += summand; - MarkDone(); - return DecodeStatus::kDecodeDone; - } - } - } - - // Signal error if value is too large or there are too many extension bytes. - HTTP2_DLOG(WARNING) - << "Variable length int encoding is too large or too long. " - << DebugString(); - MarkDone(); - return DecodeStatus::kDecodeError; -} - -uint64_t HpackVarintDecoder::value() const { - CheckDone(); - return value_; -} - -void HpackVarintDecoder::set_value(uint64_t v) { - MarkDone(); - value_ = v; -} - -std::string HpackVarintDecoder::DebugString() const { - return absl::StrCat("HpackVarintDecoder(value=", value_, ", offset=", offset_, - ")"); -} - -DecodeStatus HpackVarintDecoder::StartForTest(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db) { - return Start(prefix_value, prefix_length, db); -} - -DecodeStatus HpackVarintDecoder::StartExtendedForTest(uint8_t prefix_length, - DecodeBuffer* db) { - return StartExtended(prefix_length, db); -} - -DecodeStatus HpackVarintDecoder::ResumeForTest(DecodeBuffer* db) { - return Resume(db); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h deleted file mode 100644 index 7de72baf1ac..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h +++ /dev/null @@ -1,130 +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. - -// HpackVarintDecoder decodes HPACK variable length unsigned integers. In HPACK, -// these integers are used to identify static or dynamic table index entries, to -// specify string lengths, and to update the size limit of the dynamic table. -// In QPACK, in addition to these uses, these integers also identify streams. -// -// The caller will need to validate that the decoded value is in an acceptable -// range. -// -// For details of the encoding, see: -// http://httpwg.org/specs/rfc7541.html#integer.representation -// -// HpackVarintDecoder supports decoding any integer that can be represented on -// uint64_t, thereby exceeding the requirements for QPACK: "QPACK -// implementations MUST be able to decode integers up to 62 bits long." See -// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.1.1 -// -// This decoder supports at most 10 extension bytes (bytes following the prefix, -// also called continuation bytes). An encoder is allowed to zero pad the -// encoded integer on the left, thereby increasing the number of extension -// bytes. If an encoder uses so much padding that the number of extension bytes -// exceeds the limit, then this decoder signals an error. - -#ifndef QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ -#define QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ - -#include <cstdint> -#include <limits> -#include <string> - -#include "http2/decoder/decode_buffer.h" -#include "http2/decoder/decode_status.h" -#include "http2/platform/api/http2_logging.h" -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -// Sentinel value for |HpackVarintDecoder::offset_| to signify that decoding is -// completed. Only used in debug builds. -#ifndef NDEBUG -const uint8_t kHpackVarintDecoderOffsetDone = - std::numeric_limits<uint8_t>::max(); -#endif - -// Decodes an HPACK variable length unsigned integer, in a resumable fashion -// so it can handle running out of input in the DecodeBuffer. Call Start or -// StartExtended the first time (when decoding the byte that contains the -// prefix), then call Resume later if it is necessary to resume. When done, -// call value() to retrieve the decoded value. -// -// No constructor or destructor. Holds no resources, so destruction isn't -// needed. Start and StartExtended handles the initialization of member -// variables. This is necessary in order for HpackVarintDecoder to be part -// of a union. -class QUICHE_EXPORT_PRIVATE HpackVarintDecoder { - public: - // |prefix_value| is the first byte of the encoded varint. - // |prefix_length| is number of bits in the first byte that are used for - // encoding the integer. |db| is the rest of the buffer, that is, not - // including the first byte. - DecodeStatus Start(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db); - - // The caller has already determined that the encoding requires multiple - // bytes, i.e. that the 3 to 8 low-order bits (the number determined by - // |prefix_length|) of the first byte are are all 1. |db| is the rest of the - // buffer, that is, not including the first byte. - DecodeStatus StartExtended(uint8_t prefix_length, DecodeBuffer* db); - - // Resume decoding a variable length integer after an earlier - // call to Start or StartExtended returned kDecodeInProgress. - DecodeStatus Resume(DecodeBuffer* db); - - uint64_t value() const; - - // This supports optimizations for the case of a varint with zero extension - // bytes, where the handling of the prefix is done by the caller. - void set_value(uint64_t v); - - // All the public methods below are for supporting assertions and tests. - - std::string DebugString() const; - - // For benchmarking, these methods ensure the decoder - // is NOT inlined into the caller. - DecodeStatus StartForTest(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db); - DecodeStatus StartExtendedForTest(uint8_t prefix_length, DecodeBuffer* db); - DecodeStatus ResumeForTest(DecodeBuffer* db); - - private: - // Protection in case Resume is called when it shouldn't be. - void MarkDone() { -#ifndef NDEBUG - offset_ = kHpackVarintDecoderOffsetDone; -#endif - } - void CheckNotDone() const { -#ifndef NDEBUG - QUICHE_DCHECK_NE(kHpackVarintDecoderOffsetDone, offset_); -#endif - } - void CheckDone() const { -#ifndef NDEBUG - QUICHE_DCHECK_EQ(kHpackVarintDecoderOffsetDone, offset_); -#endif - } - - // These fields are initialized just to keep ASAN happy about reading - // them from DebugString(). - - // The encoded integer is being accumulated in |value_|. When decoding is - // complete, |value_| holds the result. - uint64_t value_ = 0; - - // Each extension byte encodes in its lowest 7 bits a segment of the integer. - // |offset_| is the number of places this segment has to be shifted to the - // left for decoding. It is zero for the first extension byte, and increases - // by 7 for each subsequent extension byte. - uint8_t offset_ = 0; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc deleted file mode 100644 index d204b333966..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2018 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/hpack/varint/hpack_varint_decoder.h" - -// Test HpackVarintDecoder against hardcoded data. - -#include <stddef.h> - -#include "absl/base/macros.h" -#include "absl/strings/escaping.h" -#include "absl/strings/string_view.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" - -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { - -class HpackVarintDecoderTest - : public RandomDecoderTest, - public ::testing::WithParamInterface<std::tuple<uint8_t, const char*>> { - protected: - HpackVarintDecoderTest() - : high_bits_(std::get<0>(GetParam())), - suffix_(absl::HexStringToBytes(std::get<1>(GetParam()))), - prefix_length_(0) {} - - void DecodeExpectSuccess(absl::string_view data, - uint32_t prefix_length, - uint64_t expected_value) { - Validator validator = [expected_value, this]( - const DecodeBuffer& /*db*/, - DecodeStatus /*status*/) -> AssertionResult { - VERIFY_EQ(expected_value, decoder_.value()) - << "Value doesn't match expected: " << decoder_.value() - << " != " << expected_value; - return AssertionSuccess(); - }; - - // First validate that decoding is done and that we've advanced the cursor - // the expected amount. - validator = ValidateDoneAndOffset(/* offset = */ data.size(), validator); - - EXPECT_TRUE(Decode(data, prefix_length, validator)); - - EXPECT_EQ(expected_value, decoder_.value()); - } - - void DecodeExpectError(absl::string_view data, uint32_t prefix_length) { - Validator validator = [](const DecodeBuffer& /*db*/, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(DecodeStatus::kDecodeError, status); - return AssertionSuccess(); - }; - - EXPECT_TRUE(Decode(data, prefix_length, validator)); - } - - private: - AssertionResult Decode(absl::string_view data, - uint32_t prefix_length, - const Validator validator) { - prefix_length_ = prefix_length; - - // Copy |data| so that it can be modified. - std::string data_copy(data); - - // Bits of the first byte not part of the prefix should be ignored. - uint8_t high_bits_mask = 0b11111111 << prefix_length_; - data_copy[0] |= (high_bits_mask & high_bits_); - - // Extra bytes appended to the input should be ignored. - data_copy.append(suffix_); - - DecodeBuffer b(data_copy); - - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - - return DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, - validator); - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - QUICHE_CHECK_LT(0u, b->Remaining()); - uint8_t prefix = b->DecodeUInt8(); - return decoder_.Start(prefix, prefix_length_, b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b); - } - - // Bits of the first byte not part of the prefix. - const uint8_t high_bits_; - // Extra bytes appended to the input. - const std::string suffix_; - - HpackVarintDecoder decoder_; - uint8_t prefix_length_; -}; - -INSTANTIATE_TEST_SUITE_P( - HpackVarintDecoderTest, - HpackVarintDecoderTest, - ::testing::Combine( - // Bits of the first byte not part of the prefix should be ignored. - ::testing::Values(0b00000000, 0b11111111, 0b10101010), - // Extra bytes appended to the input should be ignored. - ::testing::Values("", "00", "666f6f"))); - -struct { - const char* data; - uint32_t prefix_length; - uint64_t expected_value; -} kSuccessTestData[] = { - // Zero value with different prefix lengths. - {"00", 3, 0}, - {"00", 4, 0}, - {"00", 5, 0}, - {"00", 6, 0}, - {"00", 7, 0}, - {"00", 8, 0}, - // Small values that fit in the prefix. - {"06", 3, 6}, - {"0d", 4, 13}, - {"10", 5, 16}, - {"29", 6, 41}, - {"56", 7, 86}, - {"bf", 8, 191}, - // Values of 2^n-1, which have an all-zero extension byte. - {"0700", 3, 7}, - {"0f00", 4, 15}, - {"1f00", 5, 31}, - {"3f00", 6, 63}, - {"7f00", 7, 127}, - {"ff00", 8, 255}, - // Values of 2^n-1, plus one extra byte of padding. - {"078000", 3, 7}, - {"0f8000", 4, 15}, - {"1f8000", 5, 31}, - {"3f8000", 6, 63}, - {"7f8000", 7, 127}, - {"ff8000", 8, 255}, - // Values requiring one extension byte. - {"0760", 3, 103}, - {"0f2a", 4, 57}, - {"1f7f", 5, 158}, - {"3f02", 6, 65}, - {"7f49", 7, 200}, - {"ff6f", 8, 366}, - // Values requiring one extension byte, plus one byte of padding. - {"07e000", 3, 103}, - {"0faa00", 4, 57}, - {"1fff00", 5, 158}, - {"3f8200", 6, 65}, - {"7fc900", 7, 200}, - {"ffef00", 8, 366}, - // Values requiring one extension byte, plus two bytes of padding. - {"07e08000", 3, 103}, - {"0faa8000", 4, 57}, - {"1fff8000", 5, 158}, - {"3f828000", 6, 65}, - {"7fc98000", 7, 200}, - {"ffef8000", 8, 366}, - // Values requiring one extension byte, plus the maximum amount of padding. - {"07e0808080808080808000", 3, 103}, - {"0faa808080808080808000", 4, 57}, - {"1fff808080808080808000", 5, 158}, - {"3f82808080808080808000", 6, 65}, - {"7fc9808080808080808000", 7, 200}, - {"ffef808080808080808000", 8, 366}, - // Values requiring two extension bytes. - {"07b260", 3, 12345}, - {"0f8a2a", 4, 5401}, - {"1fa87f", 5, 16327}, - {"3fd002", 6, 399}, - {"7fff49", 7, 9598}, - {"ffe32f", 8, 6370}, - // Values requiring two extension bytes, plus one byte of padding. - {"07b2e000", 3, 12345}, - {"0f8aaa00", 4, 5401}, - {"1fa8ff00", 5, 16327}, - {"3fd08200", 6, 399}, - {"7fffc900", 7, 9598}, - {"ffe3af00", 8, 6370}, - // Values requiring two extension bytes, plus the maximum amount of padding. - {"07b2e080808080808000", 3, 12345}, - {"0f8aaa80808080808000", 4, 5401}, - {"1fa8ff80808080808000", 5, 16327}, - {"3fd08280808080808000", 6, 399}, - {"7fffc980808080808000", 7, 9598}, - {"ffe3af80808080808000", 8, 6370}, - // Values requiring three extension bytes. - {"078ab260", 3, 1579281}, - {"0fc18a2a", 4, 689488}, - {"1fada87f", 5, 2085964}, - {"3fa0d002", 6, 43103}, - {"7ffeff49", 7, 1212541}, - {"ff93de23", 8, 585746}, - // Values requiring three extension bytes, plus one byte of padding. - {"078ab2e000", 3, 1579281}, - {"0fc18aaa00", 4, 689488}, - {"1fada8ff00", 5, 2085964}, - {"3fa0d08200", 6, 43103}, - {"7ffeffc900", 7, 1212541}, - {"ff93dea300", 8, 585746}, - // Values requiring four extension bytes. - {"079f8ab260", 3, 202147110}, - {"0fa2c18a2a", 4, 88252593}, - {"1fd0ada87f", 5, 266999535}, - {"3ff9a0d002", 6, 5509304}, - {"7f9efeff49", 7, 155189149}, - {"ffaa82f404", 8, 10289705}, - // Values requiring four extension bytes, plus one byte of padding. - {"079f8ab2e000", 3, 202147110}, - {"0fa2c18aaa00", 4, 88252593}, - {"1fd0ada8ff00", 5, 266999535}, - {"3ff9a0d08200", 6, 5509304}, - {"7f9efeffc900", 7, 155189149}, - {"ffaa82f48400", 8, 10289705}, - // Values requiring six extension bytes. - {"0783aa9f8ab260", 3, 3311978140938}, - {"0ff0b0a2c18a2a", 4, 1445930244223}, - {"1fda84d0ada87f", 5, 4374519874169}, - {"3fb5fbf9a0d002", 6, 90263420404}, - {"7fcff19efeff49", 7, 2542616951118}, - {"ff9fa486bbc327", 8, 1358138807070}, - // Values requiring eight extension bytes. - {"07f19883aa9f8ab260", 3, 54263449861016696}, - {"0f84fdf0b0a2c18a2a", 4, 23690121121119891}, - {"1fa0dfda84d0ada87f", 5, 71672133617889215}, - {"3f9ff0b5fbf9a0d002", 6, 1478875878881374}, - {"7ffbc1cff19efeff49", 7, 41658236125045114}, - {"ff91b6fb85af99c342", 8, 37450237664484368}, - // Values requiring ten extension bytes. - {"0794f1f19883aa9f8ab201", 3, 12832019021693745307u}, - {"0fa08f84fdf0b0a2c18a01", 4, 9980690937382242223u}, - {"1fbfdda0dfda84d0ada801", 5, 12131360551794650846u}, - {"3f9dc79ff0b5fbf9a0d001", 6, 15006530362736632796u}, - {"7f8790fbc1cff19efeff01", 7, 18445754019193211014u}, - {"fffba8c5b8d3fe9f8c8401", 8, 9518498503615141242u}, - // Maximum value: 2^64-1. - {"07f8ffffffffffffffff01", 3, 18446744073709551615u}, - {"0ff0ffffffffffffffff01", 4, 18446744073709551615u}, - {"1fe0ffffffffffffffff01", 5, 18446744073709551615u}, - {"3fc0ffffffffffffffff01", 6, 18446744073709551615u}, - {"7f80ffffffffffffffff01", 7, 18446744073709551615u}, - {"ff80feffffffffffffff01", 8, 18446744073709551615u}, - // Examples from RFC7541 C.1. - {"0a", 5, 10}, - {"1f9a0a", 5, 1337}, -}; - -TEST_P(HpackVarintDecoderTest, Success) { - for (size_t i = 0; i < ABSL_ARRAYSIZE(kSuccessTestData); ++i) { - DecodeExpectSuccess(absl::HexStringToBytes(kSuccessTestData[i].data), - kSuccessTestData[i].prefix_length, - kSuccessTestData[i].expected_value); - } -} - -struct { - const char* data; - uint32_t prefix_length; -} kErrorTestData[] = { - // Too many extension bytes, all 0s (except for extension bit in each byte). - {"0780808080808080808080", 3}, - {"0f80808080808080808080", 4}, - {"1f80808080808080808080", 5}, - {"3f80808080808080808080", 6}, - {"7f80808080808080808080", 7}, - {"ff80808080808080808080", 8}, - // Too many extension bytes, all 1s. - {"07ffffffffffffffffffff", 3}, - {"0fffffffffffffffffffff", 4}, - {"1fffffffffffffffffffff", 5}, - {"3fffffffffffffffffffff", 6}, - {"7fffffffffffffffffffff", 7}, - {"ffffffffffffffffffffff", 8}, - // Value of 2^64, one higher than maximum of 2^64-1. - {"07f9ffffffffffffffff01", 3}, - {"0ff1ffffffffffffffff01", 4}, - {"1fe1ffffffffffffffff01", 5}, - {"3fc1ffffffffffffffff01", 6}, - {"7f81ffffffffffffffff01", 7}, - {"ff81feffffffffffffff01", 8}, - // Maximum value: 2^64-1, with one byte of padding. - {"07f8ffffffffffffffff8100", 3}, - {"0ff0ffffffffffffffff8100", 4}, - {"1fe0ffffffffffffffff8100", 5}, - {"3fc0ffffffffffffffff8100", 6}, - {"7f80ffffffffffffffff8100", 7}, - {"ff80feffffffffffffff8100", 8}}; - -TEST_P(HpackVarintDecoderTest, Error) { - for (size_t i = 0; i < ABSL_ARRAYSIZE(kErrorTestData); ++i) { - DecodeExpectError(absl::HexStringToBytes(kErrorTestData[i].data), - kErrorTestData[i].prefix_length); - } -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.cc deleted file mode 100644 index 87f4981bdf1..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.cc +++ /dev/null @@ -1,49 +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/hpack/varint/hpack_varint_encoder.h" - -#include <limits> - -#include "http2/platform/api/http2_logging.h" - -namespace http2 { - -// static -void HpackVarintEncoder::Encode(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint, - std::string* output) { - QUICHE_DCHECK_LE(1u, prefix_length); - QUICHE_DCHECK_LE(prefix_length, 8u); - - // prefix_mask defines the sequence of low-order bits of the first byte - // that encode the prefix of the value. It is also the marker in those bits - // of the first byte indicating that at least one extension byte is needed. - const uint8_t prefix_mask = (1 << prefix_length) - 1; - QUICHE_DCHECK_EQ(0, high_bits & prefix_mask); - - if (varint < prefix_mask) { - // The integer fits into the prefix in its entirety. - unsigned char first_byte = high_bits | static_cast<unsigned char>(varint); - output->push_back(first_byte); - return; - } - - // Extension bytes are needed. - unsigned char first_byte = high_bits | prefix_mask; - output->push_back(first_byte); - - varint -= prefix_mask; - while (varint >= 128) { - // Encode the next seven bits, with continuation bit set to one. - output->push_back(0b10000000 | (varint % 128)); - varint >>= 7; - } - - // Encode final seven bits, with continuation bit set to zero. - output->push_back(varint); -} - -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.h b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.h deleted file mode 100644 index 91eaa43e45b..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.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_HPACK_VARINT_HPACK_VARINT_ENCODER_H_ -#define QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_ENCODER_H_ - -#include <cstddef> -#include <cstdint> -#include <string> - -#include "common/platform/api/quiche_export.h" - -namespace http2 { - -// HPACK integer encoder class with single static method implementing variable -// length integer representation defined in RFC7541, Section 5.1: -// https://httpwg.org/specs/rfc7541.html#integer.representation -class QUICHE_EXPORT_PRIVATE HpackVarintEncoder { - public: - // Encode |varint|, appending encoded data to |*output|. - // Appends between 1 and 11 bytes in total. - static void Encode(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint, - std::string* output); -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_ENCODER_H_ diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc deleted file mode 100644 index 5daf88b99d7..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc +++ /dev/null @@ -1,161 +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/hpack/varint/hpack_varint_encoder.h" - -#include "absl/base/macros.h" -#include "absl/strings/escaping.h" -#include "common/platform/api/quiche_test.h" - -namespace http2 { -namespace test { -namespace { - -struct { - uint8_t high_bits; - uint8_t prefix_length; - uint64_t value; - uint8_t expected_encoding; -} kShortTestData[] = {{0b10110010, 1, 0, 0b10110010}, - {0b10101100, 2, 2, 0b10101110}, - {0b10100000, 3, 6, 0b10100110}, - {0b10110000, 4, 13, 0b10111101}, - {0b10100000, 5, 8, 0b10101000}, - {0b11000000, 6, 48, 0b11110000}, - {0b10000000, 7, 99, 0b11100011}, - // Example from RFC7541 C.1. - {0b00000000, 5, 10, 0b00001010}}; - -// Encode integers that fit in the prefix. -TEST(HpackVarintEncoderTest, Short) { - for (size_t i = 0; i < ABSL_ARRAYSIZE(kShortTestData); ++i) { - std::string output; - HpackVarintEncoder::Encode(kShortTestData[i].high_bits, - kShortTestData[i].prefix_length, - kShortTestData[i].value, &output); - ASSERT_EQ(1u, output.size()); - EXPECT_EQ(kShortTestData[i].expected_encoding, - static_cast<uint8_t>(output[0])); - } -} - -struct { - uint8_t high_bits; - uint8_t prefix_length; - uint64_t value; - const char* expected_encoding; -} kLongTestData[] = { - // One extension byte. - {0b10011000, 3, 103, "9f60"}, - {0b10010000, 4, 57, "9f2a"}, - {0b11000000, 5, 158, "df7f"}, - {0b01000000, 6, 65, "7f02"}, - {0b00000000, 7, 200, "7f49"}, - // Two extension bytes. - {0b10011000, 3, 12345, "9fb260"}, - {0b10010000, 4, 5401, "9f8a2a"}, - {0b11000000, 5, 16327, "dfa87f"}, - {0b01000000, 6, 399, "7fd002"}, - {0b00000000, 7, 9598, "7fff49"}, - // Three extension bytes. - {0b10011000, 3, 1579281, "9f8ab260"}, - {0b10010000, 4, 689488, "9fc18a2a"}, - {0b11000000, 5, 2085964, "dfada87f"}, - {0b01000000, 6, 43103, "7fa0d002"}, - {0b00000000, 7, 1212541, "7ffeff49"}, - // Four extension bytes. - {0b10011000, 3, 202147110, "9f9f8ab260"}, - {0b10010000, 4, 88252593, "9fa2c18a2a"}, - {0b11000000, 5, 266999535, "dfd0ada87f"}, - {0b01000000, 6, 5509304, "7ff9a0d002"}, - {0b00000000, 7, 155189149, "7f9efeff49"}, - // Six extension bytes. - {0b10011000, 3, 3311978140938, "9f83aa9f8ab260"}, - {0b10010000, 4, 1445930244223, "9ff0b0a2c18a2a"}, - {0b11000000, 5, 4374519874169, "dfda84d0ada87f"}, - {0b01000000, 6, 90263420404, "7fb5fbf9a0d002"}, - {0b00000000, 7, 2542616951118, "7fcff19efeff49"}, - // Eight extension bytes. - {0b10011000, 3, 54263449861016696, "9ff19883aa9f8ab260"}, - {0b10010000, 4, 23690121121119891, "9f84fdf0b0a2c18a2a"}, - {0b11000000, 5, 71672133617889215, "dfa0dfda84d0ada87f"}, - {0b01000000, 6, 1478875878881374, "7f9ff0b5fbf9a0d002"}, - {0b00000000, 7, 41658236125045114, "7ffbc1cff19efeff49"}, - // Ten extension bytes. - {0b10011000, 3, 12832019021693745307u, "9f94f1f19883aa9f8ab201"}, - {0b10010000, 4, 9980690937382242223u, "9fa08f84fdf0b0a2c18a01"}, - {0b11000000, 5, 12131360551794650846u, "dfbfdda0dfda84d0ada801"}, - {0b01000000, 6, 15006530362736632796u, "7f9dc79ff0b5fbf9a0d001"}, - {0b00000000, 7, 18445754019193211014u, "7f8790fbc1cff19efeff01"}, - // Maximum value: 2^64-1. - {0b10011000, 3, 18446744073709551615u, "9ff8ffffffffffffffff01"}, - {0b10010000, 4, 18446744073709551615u, "9ff0ffffffffffffffff01"}, - {0b11000000, 5, 18446744073709551615u, "dfe0ffffffffffffffff01"}, - {0b01000000, 6, 18446744073709551615u, "7fc0ffffffffffffffff01"}, - {0b00000000, 7, 18446744073709551615u, "7f80ffffffffffffffff01"}, - // Example from RFC7541 C.1. - {0b00000000, 5, 1337, "1f9a0a"}, -}; - -// Encode integers that do not fit in the prefix. -TEST(HpackVarintEncoderTest, Long) { - // Test encoding byte by byte, also test encoding in - // a single ResumeEncoding() call. - for (size_t i = 0; i < ABSL_ARRAYSIZE(kLongTestData); ++i) { - std::string expected_encoding = - absl::HexStringToBytes(kLongTestData[i].expected_encoding); - - std::string output; - HpackVarintEncoder::Encode(kLongTestData[i].high_bits, - kLongTestData[i].prefix_length, - kLongTestData[i].value, &output); - - EXPECT_EQ(expected_encoding, output); - } -} - -struct { - uint8_t high_bits; - uint8_t prefix_length; - uint64_t value; - uint8_t expected_encoding_first_byte; -} kLastByteIsZeroTestData[] = { - {0b10110010, 1, 1, 0b10110011}, {0b10101100, 2, 3, 0b10101111}, - {0b10101000, 3, 7, 0b10101111}, {0b10110000, 4, 15, 0b10111111}, - {0b10100000, 5, 31, 0b10111111}, {0b11000000, 6, 63, 0b11111111}, - {0b10000000, 7, 127, 0b11111111}, {0b00000000, 8, 255, 0b11111111}}; - -// Make sure that the encoder outputs the last byte even when it is zero. This -// happens exactly when encoding the value 2^prefix_length - 1. -TEST(HpackVarintEncoderTest, LastByteIsZero) { - for (size_t i = 0; i < ABSL_ARRAYSIZE(kLastByteIsZeroTestData); ++i) { - std::string output; - HpackVarintEncoder::Encode(kLastByteIsZeroTestData[i].high_bits, - kLastByteIsZeroTestData[i].prefix_length, - kLastByteIsZeroTestData[i].value, &output); - ASSERT_EQ(2u, output.size()); - EXPECT_EQ(kLastByteIsZeroTestData[i].expected_encoding_first_byte, - static_cast<uint8_t>(output[0])); - EXPECT_EQ(0b00000000, output[1]); - } -} - -// Test that encoder appends correctly to non-empty string. -TEST(HpackVarintEncoderTest, Append) { - std::string output("foo"); - EXPECT_EQ(absl::HexStringToBytes("666f6f"), output); - - HpackVarintEncoder::Encode(0b10011000, 3, 103, &output); - EXPECT_EQ(absl::HexStringToBytes("666f6f9f60"), output); - - HpackVarintEncoder::Encode(0b10100000, 5, 8, &output); - EXPECT_EQ(absl::HexStringToBytes("666f6f9f60a8"), output); - - HpackVarintEncoder::Encode(0b10011000, 3, 202147110, &output); - EXPECT_EQ(absl::HexStringToBytes("666f6f9f60a89f9f8ab260"), output); -} - -} // namespace -} // namespace test -} // namespace http2 diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc deleted file mode 100644 index 0c832d9e83a..00000000000 --- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc +++ /dev/null @@ -1,420 +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/hpack/varint/hpack_varint_decoder.h" - -// Test HpackVarintDecoder against data encoded via HpackBlockBuilder, -// which uses HpackVarintEncoder under the hood. - -#include <stddef.h> - -#include <iterator> -#include <set> -#include <vector> - -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/string_view.h" -#include "http2/hpack/tools/hpack_block_builder.h" -#include "http2/platform/api/http2_logging.h" -#include "http2/tools/random_decoder_test.h" -#include "common/platform/api/quiche_test.h" -#include "common/quiche_text_utils.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { - -// Returns the highest value with the specified number of extension bytes -// and the specified prefix length (bits). -uint64_t HiValueOfExtensionBytes(uint32_t extension_bytes, - uint32_t prefix_length) { - return (1 << prefix_length) - 2 + - (extension_bytes == 0 ? 0 : (1LLU << (extension_bytes * 7))); -} - -class HpackVarintRoundTripTest : public RandomDecoderTest { - protected: - HpackVarintRoundTripTest() : prefix_length_(0) {} - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - QUICHE_CHECK_LT(0u, b->Remaining()); - uint8_t prefix = b->DecodeUInt8(); - return decoder_.Start(prefix, prefix_length_, b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b); - } - - void DecodeSeveralWays(uint64_t expected_value, uint32_t expected_offset) { - // 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 decoder_.value() matches the expected value. - Validator validator = [expected_value, this]( - const DecodeBuffer& /*db*/, - DecodeStatus /*status*/) -> AssertionResult { - if (decoder_.value() != expected_value) { - return AssertionFailure() - << "Value doesn't match expected: " << decoder_.value() - << " != " << expected_value; - } - return AssertionSuccess(); - }; - - // First validate that decoding is done and that we've advanced the cursor - // the expected amount. - validator = ValidateDoneAndOffset(expected_offset, validator); - - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - - DecodeBuffer b(buffer_); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, validator)); - - EXPECT_EQ(expected_value, decoder_.value()); - EXPECT_EQ(expected_offset, b.Offset()); - } - - void EncodeNoRandom(uint64_t value, uint8_t prefix_length) { - QUICHE_DCHECK_LE(3, prefix_length); - QUICHE_DCHECK_LE(prefix_length, 8); - prefix_length_ = prefix_length; - - HpackBlockBuilder bb; - bb.AppendHighBitsAndVarint(0, prefix_length_, value); - buffer_ = bb.buffer(); - ASSERT_LT(0u, buffer_.size()); - - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - ASSERT_EQ(static_cast<uint8_t>(buffer_[0]), - static_cast<uint8_t>(buffer_[0]) & prefix_mask); - } - - void Encode(uint64_t value, uint8_t prefix_length) { - EncodeNoRandom(value, prefix_length); - // Add some random bits to the prefix (the first byte) above the mask. - uint8_t prefix = buffer_[0]; - buffer_[0] = prefix | (Random().Rand8() << prefix_length); - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - ASSERT_EQ(prefix, buffer_[0] & prefix_mask); - } - - // This is really a test of HpackBlockBuilder, making sure that the input to - // HpackVarintDecoder is as expected, which also acts as confirmation that - // my thinking about the encodings being used by the tests, i.e. cover the - // range desired. - void ValidateEncoding(uint64_t value, - uint64_t minimum, - uint64_t maximum, - size_t expected_bytes) { - ASSERT_EQ(expected_bytes, buffer_.size()); - if (expected_bytes > 1) { - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - EXPECT_EQ(prefix_mask, buffer_[0] & prefix_mask); - size_t last = expected_bytes - 1; - for (size_t ndx = 1; ndx < last; ++ndx) { - // Before the last extension byte, we expect the high-bit set. - uint8_t byte = buffer_[ndx]; - if (value == minimum) { - EXPECT_EQ(0x80, byte) << "ndx=" << ndx; - } else if (value == maximum) { - if (expected_bytes < 11) { - EXPECT_EQ(0xff, byte) << "ndx=" << ndx; - } - } else { - EXPECT_EQ(0x80, byte & 0x80) << "ndx=" << ndx; - } - } - // The last extension byte should not have the high-bit set. - uint8_t byte = buffer_[last]; - if (value == minimum) { - if (expected_bytes == 2) { - EXPECT_EQ(0x00, byte); - } else { - EXPECT_EQ(0x01, byte); - } - } else if (value == maximum) { - if (expected_bytes < 11) { - EXPECT_EQ(0x7f, byte); - } - } else { - EXPECT_EQ(0x00, byte & 0x80); - } - } else { - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - EXPECT_EQ(value, static_cast<uint32_t>(buffer_[0] & prefix_mask)); - EXPECT_LT(value, prefix_mask); - } - } - - void EncodeAndDecodeValues(const std::set<uint64_t>& values, - uint8_t prefix_length, - size_t expected_bytes) { - QUICHE_CHECK(!values.empty()); - const uint64_t minimum = *values.begin(); - const uint64_t maximum = *values.rbegin(); - for (const uint64_t value : values) { - Encode(value, prefix_length); // Sets buffer_. - - std::string msg = absl::StrCat("value=", value, " (0x", absl::Hex(value), - "), prefix_length=", prefix_length, - ", expected_bytes=", expected_bytes, "\n", - quiche::QuicheTextUtils::HexDump(buffer_)); - - if (value == minimum) { - HTTP2_LOG(INFO) << "Checking minimum; " << msg; - } else if (value == maximum) { - HTTP2_LOG(INFO) << "Checking maximum; " << msg; - } - - SCOPED_TRACE(msg); - ValidateEncoding(value, minimum, maximum, expected_bytes); - DecodeSeveralWays(value, expected_bytes); - - // Append some random data to the end of buffer_ and repeat. That random - // data should be ignored. - buffer_.append(Random().RandString(1 + Random().Uniform(10))); - DecodeSeveralWays(value, expected_bytes); - - // If possible, add extension bytes that don't change the value. - if (1 < expected_bytes) { - buffer_.resize(expected_bytes); - for (uint8_t total_bytes = expected_bytes + 1; total_bytes <= 6; - ++total_bytes) { - // Mark the current last byte as not being the last one. - EXPECT_EQ(0x00, 0x80 & buffer_.back()); - buffer_.back() |= 0x80; - buffer_.push_back('\0'); - DecodeSeveralWays(value, total_bytes); - } - } - } - } - - // Encode values (all or some of it) in [start, start+range). Check - // that |start| is the smallest value and |start+range-1| is the largest value - // corresponding to |expected_bytes|, except if |expected_bytes| is maximal. - void EncodeAndDecodeValuesInRange(uint64_t start, - uint64_t range, - uint8_t prefix_length, - size_t expected_bytes) { - const uint8_t prefix_mask = (1 << prefix_length) - 1; - const uint64_t beyond = start + range; - - HTTP2_LOG(INFO) - << "############################################################"; - HTTP2_LOG(INFO) << "prefix_length=" << static_cast<int>(prefix_length); - HTTP2_LOG(INFO) << "prefix_mask=" << std::hex - << static_cast<int>(prefix_mask); - HTTP2_LOG(INFO) << "start=" << start << " (" << std::hex << start << ")"; - HTTP2_LOG(INFO) << "range=" << range << " (" << std::hex << range << ")"; - HTTP2_LOG(INFO) << "beyond=" << beyond << " (" << std::hex << beyond << ")"; - HTTP2_LOG(INFO) << "expected_bytes=" << expected_bytes; - - if (expected_bytes < 11) { - // Confirm the claim that beyond requires more bytes. - Encode(beyond, prefix_length); - EXPECT_EQ(expected_bytes + 1, buffer_.size()) - << quiche::QuicheTextUtils::HexDump(buffer_); - } - - std::set<uint64_t> values; - if (range < 200) { - // Select all values in the range. - for (uint64_t offset = 0; offset < range; ++offset) { - values.insert(start + offset); - } - } else { - // Select some values in this range, including the minimum and maximum - // values that require exactly |expected_bytes| extension bytes. - values.insert({start, start + 1, beyond - 2, beyond - 1}); - while (values.size() < 100) { - values.insert(Random().UniformInRange(start, beyond - 1)); - } - } - - EncodeAndDecodeValues(values, prefix_length, expected_bytes); - } - - HpackVarintDecoder decoder_; - std::string buffer_; - uint8_t prefix_length_; -}; - -// To help me and future debuggers of varint encodings, this HTTP2_LOGs out the -// transition points where a new extension byte is added. -TEST_F(HpackVarintRoundTripTest, Encode) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t a = HiValueOfExtensionBytes(0, prefix_length); - const uint64_t b = HiValueOfExtensionBytes(1, prefix_length); - const uint64_t c = HiValueOfExtensionBytes(2, prefix_length); - const uint64_t d = HiValueOfExtensionBytes(3, prefix_length); - const uint64_t e = HiValueOfExtensionBytes(4, prefix_length); - const uint64_t f = HiValueOfExtensionBytes(5, prefix_length); - const uint64_t g = HiValueOfExtensionBytes(6, prefix_length); - const uint64_t h = HiValueOfExtensionBytes(7, prefix_length); - const uint64_t i = HiValueOfExtensionBytes(8, prefix_length); - const uint64_t j = HiValueOfExtensionBytes(9, prefix_length); - - HTTP2_LOG(INFO) - << "############################################################"; - HTTP2_LOG(INFO) << "prefix_length=" << prefix_length << " a=" << a - << " b=" << b << " c=" << c << " d=" << d - << " e=" << e << " f=" << f << " g=" << g - << " h=" << h << " i=" << i << " j=" << j; - - std::vector<uint64_t> values = { - 0, 1, // Force line break. - a - 1, a, a + 1, a + 2, a + 3, // Force line break. - b - 1, b, b + 1, b + 2, b + 3, // Force line break. - c - 1, c, c + 1, c + 2, c + 3, // Force line break. - d - 1, d, d + 1, d + 2, d + 3, // Force line break. - e - 1, e, e + 1, e + 2, e + 3, // Force line break. - f - 1, f, f + 1, f + 2, f + 3, // Force line break. - g - 1, g, g + 1, g + 2, g + 3, // Force line break. - h - 1, h, h + 1, h + 2, h + 3, // Force line break. - i - 1, i, i + 1, i + 2, i + 3, // Force line break. - j - 1, j, j + 1, j + 2, j + 3, // Force line break. - }; - - for (uint64_t value : values) { - EncodeNoRandom(value, prefix_length); - std::string dump = quiche::QuicheTextUtils::HexDump(buffer_); - HTTP2_LOG(INFO) << absl::StrFormat("%10llu %0#18x ", value, value) - << quiche::QuicheTextUtils::HexDump(buffer_).substr(7); - } - } -} - -TEST_F(HpackVarintRoundTripTest, FromSpec1337) { - DecodeBuffer b(absl::string_view("\x1f\x9a\x0a")); - uint32_t prefix_length = 5; - uint8_t p = b.DecodeUInt8(); - EXPECT_EQ(1u, b.Offset()); - EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_.Start(p, prefix_length, &b)); - EXPECT_EQ(3u, b.Offset()); - EXPECT_EQ(1337u, decoder_.value()); - - EncodeNoRandom(1337, prefix_length); - EXPECT_EQ(3u, buffer_.size()); - EXPECT_EQ('\x1f', buffer_[0]); - EXPECT_EQ('\x9a', buffer_[1]); - EXPECT_EQ('\x0a', buffer_[2]); -} - -// Test all the values that fit into the prefix (one less than the mask). -TEST_F(HpackVarintRoundTripTest, ValidatePrefixOnly) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint8_t prefix_mask = (1 << prefix_length) - 1; - EncodeAndDecodeValuesInRange(0, prefix_mask, prefix_length, 1); - } -} - -// Test all values that require exactly 1 extension byte. -TEST_F(HpackVarintRoundTripTest, ValidateOneExtensionByte) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(0, prefix_length) + 1; - EncodeAndDecodeValuesInRange(start, 128, prefix_length, 2); - } -} - -// Test *some* values that require exactly 2 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateTwoExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(1, prefix_length) + 1; - const uint64_t range = 127 << 7; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 3); - } -} - -// Test *some* values that require 3 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateThreeExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(2, prefix_length) + 1; - const uint64_t range = 127 << 14; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 4); - } -} - -// Test *some* values that require 4 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateFourExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(3, prefix_length) + 1; - const uint64_t range = 127 << 21; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 5); - } -} - -// Test *some* values that require 5 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateFiveExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(4, prefix_length) + 1; - const uint64_t range = 127llu << 28; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 6); - } -} - -// Test *some* values that require 6 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateSixExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(5, prefix_length) + 1; - const uint64_t range = 127llu << 35; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 7); - } -} - -// Test *some* values that require 7 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateSevenExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(6, prefix_length) + 1; - const uint64_t range = 127llu << 42; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 8); - } -} - -// Test *some* values that require 8 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateEightExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(7, prefix_length) + 1; - const uint64_t range = 127llu << 49; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 9); - } -} - -// Test *some* values that require 9 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateNineExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(8, prefix_length) + 1; - const uint64_t range = 127llu << 56; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 10); - } -} - -// Test *some* values that require 10 extension bytes. -TEST_F(HpackVarintRoundTripTest, ValidateTenExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(9, prefix_length) + 1; - const uint64_t range = std::numeric_limits<uint64_t>::max() - start; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 11); - } -} - -} // namespace -} // namespace test -} // namespace http2 |