// 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 "net/third_party/http2/decoder/decode_buffer.h" namespace http2 { uint8_t DecodeBuffer::DecodeUInt8() { return static_cast(DecodeChar()); } uint16_t DecodeBuffer::DecodeUInt16() { DCHECK_LE(2u, Remaining()); const uint8_t b1 = DecodeUInt8(); const uint8_t b2 = DecodeUInt8(); // Note that chars are automatically promoted to ints during arithmetic, // so the b1 << 8 doesn't end up as zero before being or-ed with b2. // And the left-shift operator has higher precedence than the or operator. return b1 << 8 | b2; } uint32_t DecodeBuffer::DecodeUInt24() { DCHECK_LE(3u, Remaining()); const uint8_t b1 = DecodeUInt8(); const uint8_t b2 = DecodeUInt8(); const uint8_t b3 = DecodeUInt8(); return b1 << 16 | b2 << 8 | b3; } uint32_t DecodeBuffer::DecodeUInt31() { DCHECK_LE(4u, Remaining()); const uint8_t b1 = DecodeUInt8() & 0x7f; // Mask out the high order bit. const uint8_t b2 = DecodeUInt8(); const uint8_t b3 = DecodeUInt8(); const uint8_t b4 = DecodeUInt8(); return b1 << 24 | b2 << 16 | b3 << 8 | b4; } uint32_t DecodeBuffer::DecodeUInt32() { DCHECK_LE(4u, Remaining()); const uint8_t b1 = DecodeUInt8(); const uint8_t b2 = DecodeUInt8(); const uint8_t b3 = DecodeUInt8(); const uint8_t b4 = DecodeUInt8(); return b1 << 24 | b2 << 16 | b3 << 8 | b4; } #ifndef NDEBUG void DecodeBuffer::set_subset_of_base(DecodeBuffer* base, const DecodeBufferSubset* subset) { DCHECK_EQ(this, subset); base->set_subset(subset); } void DecodeBuffer::clear_subset_of_base(DecodeBuffer* base, const DecodeBufferSubset* subset) { DCHECK_EQ(this, subset); base->clear_subset(subset); } void DecodeBuffer::set_subset(const DecodeBufferSubset* subset) { DCHECK(subset != nullptr); DCHECK_EQ(subset_, nullptr) << "There is already a subset"; subset_ = subset; } void DecodeBuffer::clear_subset(const DecodeBufferSubset* subset) { DCHECK(subset != nullptr); DCHECK_EQ(subset_, subset); subset_ = nullptr; } void DecodeBufferSubset::DebugSetup() { start_base_offset_ = base_buffer_->Offset(); max_base_offset_ = start_base_offset_ + FullSize(); DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); // Ensure that there is only one DecodeBufferSubset at a time for a base. set_subset_of_base(base_buffer_, this); } void DecodeBufferSubset::DebugTearDown() { // Ensure that the base hasn't been modified. DCHECK_EQ(start_base_offset_, base_buffer_->Offset()) << "The base buffer was modified"; // Ensure that we haven't gone beyond the maximum allowed offset. size_t offset = Offset(); DCHECK_LE(offset, FullSize()); DCHECK_LE(start_base_offset_ + offset, max_base_offset_); DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); clear_subset_of_base(base_buffer_, this); } #endif } // namespace http2