| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/hpack/hpack_input_stream.h" | 5 #include "net/spdy/hpack/hpack_input_stream.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "net/spdy/hpack/hpack_huffman_decoder.h" |
| 10 | 11 |
| 11 namespace net { | 12 namespace net { |
| 12 | 13 |
| 13 using base::StringPiece; | 14 using base::StringPiece; |
| 14 using std::string; | 15 using std::string; |
| 15 | 16 |
| 16 HpackInputStream::HpackInputStream(uint32_t max_string_literal_size, | 17 HpackInputStream::HpackInputStream(uint32_t max_string_literal_size, |
| 17 StringPiece buffer) | 18 StringPiece buffer) |
| 18 : max_string_literal_size_(max_string_literal_size), | 19 : max_string_literal_size_(max_string_literal_size), |
| 19 buffer_(buffer), | 20 buffer_(buffer), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 38 | 39 |
| 39 if ((peeked >> (32 - prefix.bit_size)) == prefix.bits) { | 40 if ((peeked >> (32 - prefix.bit_size)) == prefix.bits) { |
| 40 ConsumeBits(prefix.bit_size); | 41 ConsumeBits(prefix.bit_size); |
| 41 return true; | 42 return true; |
| 42 } | 43 } |
| 43 return false; | 44 return false; |
| 44 } | 45 } |
| 45 | 46 |
| 46 bool HpackInputStream::PeekNextOctet(uint8_t* next_octet) { | 47 bool HpackInputStream::PeekNextOctet(uint8_t* next_octet) { |
| 47 if ((bit_offset_ > 0) || buffer_.empty()) { | 48 if ((bit_offset_ > 0) || buffer_.empty()) { |
| 49 DVLOG(1) << "HpackInputStream::PeekNextOctet bit_offset_=" << bit_offset_; |
| 48 return false; | 50 return false; |
| 49 } | 51 } |
| 50 | 52 |
| 51 *next_octet = buffer_[0]; | 53 *next_octet = buffer_[0]; |
| 52 return true; | 54 return true; |
| 53 } | 55 } |
| 54 | 56 |
| 55 bool HpackInputStream::DecodeNextOctet(uint8_t* next_octet) { | 57 bool HpackInputStream::DecodeNextOctet(uint8_t* next_octet) { |
| 56 if (!PeekNextOctet(next_octet)) { | 58 if (!PeekNextOctet(next_octet)) { |
| 57 return false; | 59 return false; |
| 58 } | 60 } |
| 59 | 61 |
| 60 buffer_.remove_prefix(1); | 62 buffer_.remove_prefix(1); |
| 61 return true; | 63 return true; |
| 62 } | 64 } |
| 63 | 65 |
| 64 bool HpackInputStream::DecodeNextUint32(uint32_t* I) { | 66 bool HpackInputStream::DecodeNextUint32(uint32_t* I) { |
| 65 size_t N = 8 - bit_offset_; | 67 size_t N = 8 - bit_offset_; |
| 66 DCHECK_GT(N, 0u); | 68 DCHECK_GT(N, 0u); |
| 67 DCHECK_LE(N, 8u); | 69 DCHECK_LE(N, 8u); |
| 68 | 70 |
| 69 bit_offset_ = 0; | 71 bit_offset_ = 0; |
| 70 | 72 |
| 71 *I = 0; | 73 *I = 0; |
| 72 | 74 |
| 73 uint8_t next_marker = (1 << N) - 1; | 75 uint8_t next_marker = (1 << N) - 1; |
| 74 uint8_t next_octet = 0; | 76 uint8_t next_octet = 0; |
| 75 if (!DecodeNextOctet(&next_octet)) { | 77 if (!DecodeNextOctet(&next_octet)) { |
| 78 DVLOG(1) << "HpackInputStream::DecodeNextUint32 initial octet error"; |
| 76 return false; | 79 return false; |
| 77 } | 80 } |
| 78 *I = next_octet & next_marker; | 81 *I = next_octet & next_marker; |
| 79 | 82 |
| 80 bool has_more = (*I == next_marker); | 83 bool has_more = (*I == next_marker); |
| 81 size_t shift = 0; | 84 size_t shift = 0; |
| 82 while (has_more && (shift < 32)) { | 85 while (has_more && (shift < 32)) { |
| 83 uint8_t next_octet = 0; | 86 uint8_t next_octet = 0; |
| 84 if (!DecodeNextOctet(&next_octet)) { | 87 if (!DecodeNextOctet(&next_octet)) { |
| 88 DVLOG(1) << "HpackInputStream::DecodeNextUint32 shift=" << shift; |
| 85 return false; | 89 return false; |
| 86 } | 90 } |
| 87 has_more = (next_octet & 0x80) != 0; | 91 has_more = (next_octet & 0x80) != 0; |
| 88 next_octet &= 0x7f; | 92 next_octet &= 0x7f; |
| 89 uint32_t addend = next_octet << shift; | 93 uint32_t addend = next_octet << shift; |
| 90 // Check for overflow. | 94 // Check for overflow. |
| 91 if ((addend >> shift) != next_octet) { | 95 if ((addend >> shift) != next_octet) { |
| 96 DVLOG(1) << "HpackInputStream::DecodeNextUint32 overflow"; |
| 92 return false; | 97 return false; |
| 93 } | 98 } |
| 94 *I += addend; | 99 *I += addend; |
| 95 shift += 7; | 100 shift += 7; |
| 96 } | 101 } |
| 97 | 102 |
| 98 return !has_more; | 103 return !has_more; |
| 99 } | 104 } |
| 100 | 105 |
| 101 bool HpackInputStream::DecodeNextIdentityString(StringPiece* str) { | 106 bool HpackInputStream::DecodeNextIdentityString(StringPiece* str) { |
| 102 uint32_t size = 0; | 107 uint32_t size = 0; |
| 103 if (!DecodeNextUint32(&size)) { | 108 if (!DecodeNextUint32(&size)) { |
| 104 return false; | 109 return false; |
| 105 } | 110 } |
| 106 | 111 |
| 107 if (size > max_string_literal_size_) { | 112 if (size > max_string_literal_size_) { |
| 108 return false; | 113 return false; |
| 109 } | 114 } |
| 110 | 115 |
| 111 if (size > buffer_.size()) { | 116 if (size > buffer_.size()) { |
| 112 return false; | 117 return false; |
| 113 } | 118 } |
| 114 | 119 |
| 115 *str = StringPiece(buffer_.data(), size); | 120 *str = StringPiece(buffer_.data(), size); |
| 116 buffer_.remove_prefix(size); | 121 buffer_.remove_prefix(size); |
| 117 return true; | 122 return true; |
| 118 } | 123 } |
| 119 | 124 |
| 120 bool HpackInputStream::DecodeNextHuffmanString(const HpackHuffmanTable& table, | 125 bool HpackInputStream::DecodeNextHuffmanString(string* str) { |
| 121 string* str) { | |
| 122 uint32_t encoded_size = 0; | 126 uint32_t encoded_size = 0; |
| 123 if (!DecodeNextUint32(&encoded_size)) { | 127 if (!DecodeNextUint32(&encoded_size)) { |
| 128 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString " |
| 129 << "unable to decode size"; |
| 124 return false; | 130 return false; |
| 125 } | 131 } |
| 126 | 132 |
| 127 if (encoded_size > buffer_.size()) { | 133 if (encoded_size > buffer_.size()) { |
| 134 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString " << encoded_size |
| 135 << " > " << buffer_.size(); |
| 128 return false; | 136 return false; |
| 129 } | 137 } |
| 130 | 138 |
| 131 HpackInputStream bounded_reader(max_string_literal_size_, | 139 HpackInputStream bounded_reader(max_string_literal_size_, |
| 132 StringPiece(buffer_.data(), encoded_size)); | 140 StringPiece(buffer_.data(), encoded_size)); |
| 133 buffer_.remove_prefix(encoded_size); | 141 buffer_.remove_prefix(encoded_size); |
| 134 | 142 |
| 135 // HpackHuffmanTable will not decode beyond |max_string_literal_size_|. | 143 // DecodeString will not append more than |max_string_literal_size_| chars |
| 136 return table.DecodeString(&bounded_reader, max_string_literal_size_, str); | 144 // to |str|. |
| 145 return HpackHuffmanDecoder::DecodeString(&bounded_reader, |
| 146 max_string_literal_size_, str); |
| 137 } | 147 } |
| 138 | 148 |
| 139 bool HpackInputStream::PeekBits(size_t* peeked_count, uint32_t* out) const { | 149 bool HpackInputStream::PeekBits(size_t* peeked_count, uint32_t* out) const { |
| 140 size_t byte_offset = (bit_offset_ + *peeked_count) / 8; | 150 size_t byte_offset = (bit_offset_ + *peeked_count) / 8; |
| 141 size_t bit_offset = (bit_offset_ + *peeked_count) % 8; | 151 size_t bit_offset = (bit_offset_ + *peeked_count) % 8; |
| 142 | 152 |
| 143 if (*peeked_count >= 32 || byte_offset >= buffer_.size()) { | 153 if (*peeked_count >= 32 || byte_offset >= buffer_.size()) { |
| 144 return false; | 154 return false; |
| 145 } | 155 } |
| 146 // We'll read the minimum of the current byte remainder, | 156 // We'll read the minimum of the current byte remainder, |
| 147 // and the remaining unfilled bits of |out|. | 157 // and the remaining unfilled bits of |out|. |
| 148 size_t bits_to_read = std::min(32 - *peeked_count, 8 - bit_offset); | 158 size_t bits_to_read = std::min(32 - *peeked_count, 8 - bit_offset); |
| 149 | 159 |
| 150 uint32_t new_bits = static_cast<uint32_t>(buffer_[byte_offset]); | 160 uint32_t new_bits = static_cast<uint32_t>(buffer_[byte_offset]); |
| 151 // Shift byte remainder to most-signifcant bits of |new_bits|. | 161 // Shift byte remainder to most-signifcant bits of |new_bits|. |
| 152 // This drops the leading |bit_offset| bits of the byte. | 162 // This drops the leading |bit_offset| bits of the byte. |
| 153 new_bits = new_bits << (24 + bit_offset); | 163 new_bits = new_bits << (24 + bit_offset); |
| 154 // Shift bits to the most-significant open bits of |out|. | 164 // Shift bits to the most-significant open bits of |out|. |
| 155 new_bits = new_bits >> *peeked_count; | 165 new_bits = new_bits >> *peeked_count; |
| 156 | 166 |
| 157 CHECK_EQ(*out & new_bits, 0u); | 167 CHECK_EQ(*out & new_bits, 0u); |
| 158 *out |= new_bits; | 168 *out |= new_bits; |
| 159 | 169 |
| 160 *peeked_count += bits_to_read; | 170 *peeked_count += bits_to_read; |
| 161 return true; | 171 return true; |
| 162 } | 172 } |
| 163 | 173 |
| 174 std::pair<size_t, uint32_t> HpackInputStream::InitializePeekBits() { |
| 175 size_t peeked_count = 0; |
| 176 uint32_t bits = 0; |
| 177 if (bit_offset_ == 0) { |
| 178 switch (buffer_.size()) { |
| 179 default: |
| 180 DCHECK_LE(4u, buffer_.size()); |
| 181 bits = static_cast<uint32_t>(static_cast<unsigned char>(buffer_[3])); |
| 182 peeked_count += 8; |
| 183 /* FALLTHROUGH */ |
| 184 case 3: |
| 185 bits |= (static_cast<uint32_t>(static_cast<unsigned char>(buffer_[2])) |
| 186 << 8); |
| 187 peeked_count += 8; |
| 188 /* FALLTHROUGH */ |
| 189 case 2: |
| 190 bits |= (static_cast<uint32_t>(static_cast<unsigned char>(buffer_[1])) |
| 191 << 16); |
| 192 peeked_count += 8; |
| 193 /* FALLTHROUGH */ |
| 194 case 1: |
| 195 bits |= (static_cast<uint32_t>(static_cast<unsigned char>(buffer_[0])) |
| 196 << 24); |
| 197 peeked_count += 8; |
| 198 break; |
| 199 case 0: |
| 200 break; |
| 201 } |
| 202 } else { |
| 203 LOG(DFATAL) << "InitializePeekBits called with non-zero bit_offset_: " |
| 204 << bit_offset_; |
| 205 } |
| 206 return std::make_pair(peeked_count, bits); |
| 207 } |
| 208 |
| 164 void HpackInputStream::ConsumeBits(size_t bit_count) { | 209 void HpackInputStream::ConsumeBits(size_t bit_count) { |
| 165 size_t byte_count = (bit_offset_ + bit_count) / 8; | 210 size_t byte_count = (bit_offset_ + bit_count) / 8; |
| 166 bit_offset_ = (bit_offset_ + bit_count) % 8; | 211 bit_offset_ = (bit_offset_ + bit_count) % 8; |
| 167 CHECK_GE(buffer_.size(), byte_count); | 212 CHECK_GE(buffer_.size(), byte_count); |
| 168 if (bit_offset_ != 0) { | 213 if (bit_offset_ != 0) { |
| 169 CHECK_GT(buffer_.size(), 0u); | 214 CHECK_GT(buffer_.size(), 0u); |
| 170 } | 215 } |
| 171 buffer_.remove_prefix(byte_count); | 216 buffer_.remove_prefix(byte_count); |
| 172 } | 217 } |
| 173 | 218 |
| 174 void HpackInputStream::ConsumeByteRemainder() { | 219 void HpackInputStream::ConsumeByteRemainder() { |
| 175 if (bit_offset_ != 0) { | 220 if (bit_offset_ != 0) { |
| 176 ConsumeBits(8 - bit_offset_); | 221 ConsumeBits(8 - bit_offset_); |
| 177 } | 222 } |
| 178 } | 223 } |
| 179 | 224 |
| 180 } // namespace net | 225 } // namespace net |
| OLD | NEW |