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 |