proxygen
HPACKDecodeBuffer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
11 
12 #include <limits>
13 #include <memory>
15 
16 using folly::IOBuf;
17 using std::unique_ptr;
19 
20 namespace proxygen {
21 
23  return remainingBytes_ == 0;
24 }
25 
27  CHECK_GT(remainingBytes_, 0);
28  // in case we are the end of an IOBuf, peek() will move to the next one
29  uint8_t byte = peek();
30  cursor_.skip(1);
32 
33  return byte;
34 }
35 
37  CHECK_GT(remainingBytes_, 0);
38  if (cursor_.length() == 0) {
39  cursor_.peek();
40  }
41  return *cursor_.data();
42 }
43 
45  return decodeLiteral(7, literal);
46 }
47 
49  folly::fbstring& literal) {
50  literal.clear();
51  if (remainingBytes_ == 0) {
52  LOG(ERROR) << "remainingBytes_ == 0";
53  return DecodeError::BUFFER_UNDERFLOW;
54  }
55  auto byte = peek();
56  uint8_t huffmanCheck = uint8_t(1 << nbit);
57  bool huffman = byte & huffmanCheck;
58  // extract the size
59  uint64_t size;
60  DecodeError result = decodeInteger(nbit, size);
61  if (result != DecodeError::NONE) {
62  LOG(ERROR) << "Could not decode literal size";
63  return result;
64  }
65  if (size > remainingBytes_) {
66  LOG(ERROR) << "size > remainingBytes_ decoding literal size="
67  << size << " remainingBytes_=" << remainingBytes_;
68  return DecodeError::BUFFER_UNDERFLOW;
69  }
70  if (size > maxLiteralSize_) {
71  LOG(ERROR) << "Literal too large, size=" << size;
72  return DecodeError::LITERAL_TOO_LARGE;
73  }
74  const uint8_t* data;
75  unique_ptr<IOBuf> tmpbuf;
76  // handle the case where the buffer spans multiple buffers
77  if (cursor_.length() >= size) {
78  data = cursor_.data();
79  cursor_.skip(size);
80  } else {
81  // temporary buffer to pull the chunks together
82  tmpbuf = IOBuf::create(size);
83  // pull() will move the cursor
84  cursor_.pull(tmpbuf->writableData(), size);
85  data = tmpbuf->data();
86  }
87  if (huffman) {
88  static auto& huffmanTree = huffman::huffTree();
89  huffmanTree.decode(data, size, literal);
90  } else {
91  literal.append((const char *)data, size);
92  }
94  return DecodeError::NONE;
95 }
96 
98  return decodeInteger(8, integer);
99 }
100 
102  if (remainingBytes_ == 0) {
103  LOG(ERROR) << "remainingBytes_ == 0";
104  return DecodeError::BUFFER_UNDERFLOW;
105  }
106  uint8_t byte = next();
107  uint8_t mask = HPACK::NBIT_MASKS[nbit];
108  // remove the first (8 - nbit) bits
109  byte = byte & mask;
110  integer = byte;
111  if (byte != mask) {
112  // the value fit in one byte
113  return DecodeError::NONE;
114  }
115  uint64_t f = 1;
116  uint32_t fexp = 0;
117  do {
118  if (remainingBytes_ == 0) {
119  LOG(ERROR) << "remainingBytes_ == 0";
120  return DecodeError::BUFFER_UNDERFLOW;
121  }
122  byte = next();
123  if (fexp > 64) {
124  // overflow in factorizer, f > 2^64
125  LOG(ERROR) << "overflow fexp=" << fexp;
126  return DecodeError::INTEGER_OVERFLOW;
127  }
128  uint64_t add = (byte & 127) * f;
129  if (std::numeric_limits<uint64_t>::max() - integer < add) {
130  // overflow detected
131  LOG(ERROR) << "overflow integer=" << integer << " add=" << add;
132  return DecodeError::INTEGER_OVERFLOW;
133  }
134  integer += add;
135  f = f << 7;
136  fexp += 7;
137  } while (byte & 128);
138  return DecodeError::NONE;
139 }
140 namespace HPACK {
141 std::ostream& operator<<(std::ostream& os, DecodeError err) {
142  return os << static_cast<uint32_t>(err);
143 }
144 }
145 }
const uint8_t * data() const
Definition: Cursor.h:105
auto f
folly::io::Cursor & cursor_
LogLevel max
Definition: LogLevel.cpp:31
auto add
Definition: BaseTest.cpp:70
std::ostream & operator<<(std::ostream &os, const HeaderTable &table)
const uint8_t * data() const
Definition: IOBuf.h:499
void pull(void *buf, size_t len)
Definition: Cursor.h:418
std::pair< const uint8_t *, size_t > peek()
Definition: Cursor.h:451
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
uint8_t * writableData()
Definition: IOBuf.h:509
HPACK::DecodeError decodeLiteral(folly::fbstring &literal)
size_t length() const
Definition: Cursor.h:118
void skip(size_t len)
Definition: Cursor.h:371
HPACK::DecodeError decodeInteger(uint8_t nbit, uint64_t &integer)
const HuffTree & huffTree()
Definition: Huffman.cpp:252
basic_fbstring & append(const basic_fbstring &str)
Definition: FBString.h:1953
const uint8_t NBIT_MASKS[9]
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43