summaryrefslogtreecommitdiff
path: root/chromium/net/http2/decoder/decode_buffer.cc
blob: dc395ea0d0e4e08d9aec6eaa4d30f7aae87b90e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// 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/http2/decoder/decode_buffer.h"

namespace net {

uint8_t DecodeBuffer::DecodeUInt8() {
  return static_cast<uint8_t>(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 net