| OLD | NEW |
| (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(¤t_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(¤t_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 |
| OLD | NEW |