Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: components/safe_browsing_db/v4_rice.cc

Issue 2183433002: PVer4: RICE decode bytes to list of uint32 or 4-byte hash prefixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/RICE/Rice and use safe-math to check integer overflow Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/safe_browsing_db/v4_rice.h ('k') | components/safe_browsing_db/v4_rice_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/logging.h"
6 #include "base/numerics/safe_math.h"
7 #include "base/strings/stringprintf.h"
8 #include "components/safe_browsing_db/v4_rice.h"
9
10 using ::google::protobuf::RepeatedField;
11 using ::google::protobuf::int32;
12
13 namespace safe_browsing {
14
15 namespace {
16
17 const unsigned int kMaxBitIndex = 8 * sizeof(uint32_t);
18
19 void GetBytesFromUInt32(uint32_t word, char* bytes) {
20 const size_t mask = 0xFF;
21 bytes[0] = (char)(word & mask);
22 bytes[1] = (char)((word >> 8) & mask);
23 bytes[2] = (char)((word >> 16) & mask);
24 bytes[3] = (char)((word >> 24) & mask);
25 }
26
27 } // namespace
28
29 // static
30 V4DecodeResult V4RiceDecoder::ValidateInput(const int32 rice_parameter,
31 const int32 num_entries,
32 const std::string& encoded_data) {
33 if (num_entries < 0) {
34 NOTREACHED();
35 return NUM_ENTRIES_NEGATIVE_FAILURE;
36 }
37
38 if (num_entries == 0) {
39 return DECODE_SUCCESS;
40 }
41
42 if (rice_parameter <= 0) {
43 NOTREACHED();
44 return RICE_PARAMETER_NON_POSITIVE_FAILURE;
45 }
46
47 if (encoded_data.empty()) {
48 NOTREACHED();
49 return ENCODED_DATA_UNEXPECTED_EMPTY_FAILURE;
50 }
51
52 return DECODE_SUCCESS;
53 }
54
55 // static
56 V4DecodeResult V4RiceDecoder::DecodeIntegers(const int32 first_value,
57 const int32 rice_parameter,
58 const int32 num_entries,
59 const std::string& encoded_data,
60 RepeatedField<int32>* out) {
61 DCHECK(out);
62
63 V4DecodeResult result =
64 ValidateInput(rice_parameter, num_entries, encoded_data);
65 if (result != DECODE_SUCCESS) {
66 return result;
67 }
68
69 out->Reserve(num_entries + 1);
70 base::CheckedNumeric<int32> last_value(first_value);
71 out->Add(last_value.ValueOrDie());
72 if (num_entries == 0) {
73 return DECODE_SUCCESS;
74 }
75
76 V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data);
77 while (decoder.HasAnotherValue()) {
78 uint32_t offset;
79 result = decoder.GetNextValue(&offset);
80 if (result != DECODE_SUCCESS) {
81 return result;
82 }
83
84 last_value += offset;
85 if (!last_value.IsValid()) {
86 NOTREACHED();
87 return DECODED_INTEGER_OVERFLOW_FAILURE;
88 }
89
90 out->Add(last_value.ValueOrDie());
91 }
92
93 return DECODE_SUCCESS;
94 }
95
96 // static
97 V4DecodeResult V4RiceDecoder::DecodeBytes(const int32 first_value,
98 const int32 rice_parameter,
99 const int32 num_entries,
100 const std::string& encoded_data,
101 std::string* out) {
102 DCHECK(out);
103
104 V4DecodeResult result =
105 ValidateInput(rice_parameter, num_entries, encoded_data);
106 if (result != DECODE_SUCCESS) {
107 return result;
108 }
109
110 out->reserve((num_entries + 1) * 4);
111 char bytes[4];
112 base::CheckedNumeric<uint32_t> last_value(first_value);
113 GetBytesFromUInt32(last_value.ValueOrDie(), bytes);
114 out->append(bytes, 4);
115
116 if (num_entries == 0) {
117 return DECODE_SUCCESS;
118 }
119
120 V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data);
121 while (decoder.HasAnotherValue()) {
122 uint32_t offset;
123 result = decoder.GetNextValue(&offset);
124 if (result != DECODE_SUCCESS) {
125 return result;
126 }
127
128 last_value += offset;
129 if (!last_value.IsValid()) {
130 NOTREACHED();
131 return DECODED_INTEGER_OVERFLOW_FAILURE;
132 }
133
134 GetBytesFromUInt32(last_value.ValueOrDie(), bytes);
135 out->append(bytes, 4);
136 }
137
138 return DECODE_SUCCESS;
139 }
140
141 V4RiceDecoder::V4RiceDecoder(const int rice_parameter,
142 const int num_entries,
143 const std::string& encoded_data)
144 : rice_parameter_(rice_parameter),
145 num_entries_(num_entries),
146 data_(encoded_data),
147 current_word_(0) {
148 DCHECK_LE(0, num_entries_);
149 DCHECK_LE(2u, rice_parameter_);
150 DCHECK_GE(28u, rice_parameter_);
151
152 data_byte_index_ = 0;
153 current_word_bit_index_ = kMaxBitIndex;
154 }
155
156 V4RiceDecoder::~V4RiceDecoder() {}
157
158 bool V4RiceDecoder::HasAnotherValue() const {
159 return num_entries_ > 0;
160 }
161
162 V4DecodeResult V4RiceDecoder::GetNextValue(uint32_t* value) {
163 if (!HasAnotherValue()) {
164 return DECODE_NO_MORE_ENTRIES_FAILURE;
165 }
166
167 V4DecodeResult result;
168 uint32_t q = 0;
169 uint32_t bit;
170 do {
171 result = GetNextBits(1, &bit);
172 if (result != DECODE_SUCCESS) {
173 return result;
174 }
175 q += bit;
176 } while (bit);
177 uint32_t r = 0;
178 result = GetNextBits(rice_parameter_, &r);
179 if (result != DECODE_SUCCESS) {
180 return result;
181 }
182
183 *value = (q << rice_parameter_) + r;
184 num_entries_--;
185 return DECODE_SUCCESS;
186 }
187
188 V4DecodeResult V4RiceDecoder::GetNextWord(uint32_t* word) {
189 if (data_byte_index_ >= data_.size()) {
190 return DECODE_RAN_OUT_OF_BITS_FAILURE;
191 }
192
193 const size_t mask = 0xFF;
194 *word = (data_[data_byte_index_] & mask);
195 data_byte_index_++;
196 current_word_bit_index_ = 0;
197
198 if (data_byte_index_ < data_.size()) {
199 *word |= ((data_[data_byte_index_] & mask) << 8);
200 data_byte_index_++;
201
202 if (data_byte_index_ < data_.size()) {
203 *word |= ((data_[data_byte_index_] & mask) << 16);
204 data_byte_index_++;
205
206 if (data_byte_index_ < data_.size()) {
207 *word |= ((data_[data_byte_index_] & mask) << 24);
208 data_byte_index_++;
209 }
210 }
211 }
212
213 return DECODE_SUCCESS;
214 }
215
216 V4DecodeResult V4RiceDecoder::GetNextBits(unsigned int num_requested_bits,
217 uint32_t* x) {
218 if (num_requested_bits > kMaxBitIndex) {
219 NOTREACHED();
220 return DECODE_REQUESTED_TOO_MANY_BITS_FAILURE;
221 }
222
223 if (current_word_bit_index_ == kMaxBitIndex) {
224 V4DecodeResult result = GetNextWord(&current_word_);
225 if (result != DECODE_SUCCESS) {
226 return result;
227 }
228 }
229
230 unsigned int num_bits_left_in_current_word =
231 kMaxBitIndex - current_word_bit_index_;
232 if (num_bits_left_in_current_word >= num_requested_bits) {
233 // All the bits that we need are in |current_word_|.
234 GetBitsFromCurrentWord(num_requested_bits, x);
235 } else {
236 // |current_word_| contains fewer bits than we need so we store the current
237 // value of |current_word_| in |lower|, then read in a new |current_word_|,
238 // and then pick the remaining bits from the new value of |current_word_|.
239 uint32_t lower = current_word_;
240 // Bits we need after we read all of |current_word_|
241 unsigned int num_bits_from_next_word =
242 num_requested_bits - num_bits_left_in_current_word;
243 uint32_t upper;
244 V4DecodeResult result = GetNextWord(&current_word_);
245 if (result != DECODE_SUCCESS) {
246 return result;
247 }
248 GetBitsFromCurrentWord(num_bits_from_next_word, &upper);
249 *x = (upper << (num_requested_bits - num_bits_from_next_word)) | lower;
250 }
251 return DECODE_SUCCESS;
252 }
253
254 void V4RiceDecoder::GetBitsFromCurrentWord(unsigned int num_requested_bits,
255 uint32_t* x) {
256 uint32_t mask = 0xFFFFFFFF >> (kMaxBitIndex - num_requested_bits);
257 *x = current_word_ & mask;
258 current_word_ = current_word_ >> num_requested_bits;
259 current_word_bit_index_ += num_requested_bits;
260 };
261
262 std::string V4RiceDecoder::DebugString() const {
263 return base::StringPrintf(
264 "current_word_: %x; data_byte_index_; %x, "
265 "current_word_bit_index_: %x; rice_parameter_: %x",
266 current_word_, data_byte_index_, current_word_bit_index_,
267 rice_parameter_);
268 }
269
270 std::ostream& operator<<(std::ostream& os, const V4RiceDecoder& rice_decoder) {
271 os << rice_decoder.DebugString();
272 return os;
273 }
274
275 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « components/safe_browsing_db/v4_rice.h ('k') | components/safe_browsing_db/v4_rice_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698