Commit 6c5502c2 authored by Dianna Hu's avatar Dianna Hu Committed by Commit Bot

Nix HpackVarintDecoder::Max{ExtensionBytes,Offset}

The motivation is to prepare HpackVarintDecoder to conditionally support
62 bit integers as required by the QPACK specs.  This will of course
have to be flag protected.  HpackVarintDecoder::MaxExtensionBytes() and
MaxOffset() would need to return different values depending on the value
of the flag.  It's a lot easier to get rid of them instead.

In HpackVarintDecoder::Resume(), use a locally defined const instead of
MaxOffset().

In MarkDone() et al., use numeric_limits::max() instead of |MaxOffset()
+ 7|.  This value is so large that it does not matter if
HpackVarintDecoder is in up-to-28-bit-mode or up-to-62-bit-mode.  Avoid
using a method to cut down on clutter in release builds.

In HpackVarintDecoderTest.ValueTooLarge, hardcode the large value.  It
does not hurt to reduce logic in tests anyway.

This CL lands server change 214703557 by bnc.

BUG=488484

Change-Id: Ie12bfda99b478549bcc5b126be54e51804c0d85c
Reviewed-on: https://chromium-review.googlesource.com/c/1291592
Commit-Queue: Dianna Hu <diannahu@chromium.org>
Reviewed-by: default avatarRyan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601269}
parent 0d08508e
...@@ -42,13 +42,14 @@ DecodeStatus HpackVarintDecoder::StartExtended(uint8_t prefix_length, ...@@ -42,13 +42,14 @@ DecodeStatus HpackVarintDecoder::StartExtended(uint8_t prefix_length,
} }
DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) { DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) {
const uint32_t kMaxOffset = 28;
CheckNotDone(); CheckNotDone();
do { do {
if (db->Empty()) { if (db->Empty()) {
return DecodeStatus::kDecodeInProgress; return DecodeStatus::kDecodeInProgress;
} }
uint8_t byte = db->DecodeUInt8(); uint8_t byte = db->DecodeUInt8();
if (offset_ == MaxOffset() && byte != 0) if (offset_ == kMaxOffset && byte != 0)
break; break;
value_ += (byte & 0x7f) << offset_; value_ += (byte & 0x7f) << offset_;
if ((byte & 0x80) == 0) { if ((byte & 0x80) == 0) {
...@@ -56,7 +57,7 @@ DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) { ...@@ -56,7 +57,7 @@ DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) {
return DecodeStatus::kDecodeDone; return DecodeStatus::kDecodeDone;
} }
offset_ += 7; offset_ += 7;
} while (offset_ <= MaxOffset()); } while (offset_ <= kMaxOffset);
DLOG(WARNING) << "Variable length int encoding is too large or too long. " DLOG(WARNING) << "Variable length int encoding is too large or too long. "
<< DebugString(); << DebugString();
MarkDone(); MarkDone();
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
// For details of the encoding, see: // For details of the encoding, see:
// http://httpwg.org/specs/rfc7541.html#integer.representation // http://httpwg.org/specs/rfc7541.html#integer.representation
// //
// The decoder supports decoding integers up to 2^28 + 2^prefix_length - 2.
//
// TODO(jamessynge): Consider dropping support for encodings of more than 4 // TODO(jamessynge): Consider dropping support for encodings of more than 4
// bytes, including the prefix byte, as in practice we only see at most 3 bytes, // bytes, including the prefix byte, as in practice we only see at most 3 bytes,
// and 4 bytes would cover any desire to support large (but not ridiculously // and 4 bytes would cover any desire to support large (but not ridiculously
...@@ -28,6 +30,7 @@ ...@@ -28,6 +30,7 @@
#define NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ #define NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_
#include <cstdint> #include <cstdint>
#include <limits>
#include "base/logging.h" #include "base/logging.h"
#include "net/third_party/http2/decoder/decode_buffer.h" #include "net/third_party/http2/decoder/decode_buffer.h"
...@@ -84,30 +87,23 @@ class HTTP2_EXPORT_PRIVATE HpackVarintDecoder { ...@@ -84,30 +87,23 @@ class HTTP2_EXPORT_PRIVATE HpackVarintDecoder {
DecodeStatus StartExtendedForTest(uint8_t prefix_length, DecodeBuffer* db); DecodeStatus StartExtendedForTest(uint8_t prefix_length, DecodeBuffer* db);
DecodeStatus ResumeForTest(DecodeBuffer* db); DecodeStatus ResumeForTest(DecodeBuffer* db);
static constexpr uint32_t MaxExtensionBytes() { return 5; }
private: private:
// Protection in case Resume is called when it shouldn't be. // Protection in case Resume is called when it shouldn't be.
void MarkDone() { void MarkDone() {
#ifndef NDEBUG #ifndef NDEBUG
// We support up to 5 extension bytes, so offset_ should never be > 28 when offset_ = std::numeric_limits<uint32_t>::max();
// it makes sense to call Resume().
offset_ = MaxOffset() + 7;
#endif #endif
} }
void CheckNotDone() const { void CheckNotDone() const {
#ifndef NDEBUG #ifndef NDEBUG
DCHECK_LE(offset_, MaxOffset()); DCHECK_NE(std::numeric_limits<uint32_t>::max(), offset_);
#endif #endif
} }
void CheckDone() const { void CheckDone() const {
#ifndef NDEBUG #ifndef NDEBUG
DCHECK_GT(offset_, MaxOffset()); DCHECK_EQ(std::numeric_limits<uint32_t>::max(), offset_);
#endif #endif
} }
static constexpr uint32_t MaxOffset() {
return 7 * (MaxExtensionBytes() - 1);
}
// These fields are initialized just to keep ASAN happy about reading // These fields are initialized just to keep ASAN happy about reading
// them from DebugString(). // them from DebugString().
......
...@@ -336,12 +336,11 @@ TEST_F(HpackVarintRoundTripTest, ValidateFourExtensionBytes) { ...@@ -336,12 +336,11 @@ TEST_F(HpackVarintRoundTripTest, ValidateFourExtensionBytes) {
} }
} }
// Test *some* values that require too many extension bytes. // Test the value one larger than the largest that can be decoded.
TEST_F(HpackVarintRoundTripTest, ValueTooLarge) { TEST_F(HpackVarintRoundTripTest, ValueTooLarge) {
const uint32_t expected_offset = HpackVarintDecoder::MaxExtensionBytes() + 1;
for (prefix_length_ = 3; prefix_length_ <= 7; ++prefix_length_) { for (prefix_length_ = 3; prefix_length_ <= 7; ++prefix_length_) {
uint64_t too_large = HiValueOfExtensionBytes( const uint64_t too_large = (1 << 28) + (1 << prefix_length_) - 1;
HpackVarintDecoder::MaxExtensionBytes() + 3, prefix_length_); const uint32_t expected_offset = 6;
HpackBlockBuilder bb; HpackBlockBuilder bb;
bb.AppendHighBitsAndVarint(0, prefix_length_, too_large); bb.AppendHighBitsAndVarint(0, prefix_length_, too_large);
buffer_ = bb.buffer(); buffer_ = bb.buffer();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment