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

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

Issue 2228393003: PVer4: DecodeHashes needs to sort the output of the Rice decoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@01_checksum
Patch Set: Fix the test to expect sorted list of hashes from DecodeBytes 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 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 "base/logging.h" 5 #include <set>
6
6 #include "base/numerics/safe_math.h" 7 #include "base/numerics/safe_math.h"
7 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
8 #include "components/safe_browsing_db/v4_rice.h" 9 #include "components/safe_browsing_db/v4_rice.h"
9 10
10 using ::google::protobuf::RepeatedField; 11 using ::google::protobuf::RepeatedField;
11 using ::google::protobuf::int32; 12 using ::google::protobuf::int32;
13 using ::google::protobuf::int64;
12 14
13 namespace safe_browsing { 15 namespace safe_browsing {
14 16
15 namespace { 17 namespace {
16 18
17 const int kBitsPerByte = 8; 19 const int kBitsPerByte = 8;
18 const unsigned int kMaxBitIndex = kBitsPerByte * sizeof(uint32_t); 20 const unsigned int kMaxBitIndex = kBitsPerByte * sizeof(uint32_t);
19 21
22 uint32_t FlipEndianness(uint32_t word) {
Nathan Parker 2016/08/12 23:01:49 This should be platform-specific. Maybe use C's h
vakh (use Gerrit instead) 2016/08/13 00:15:13 Waiting for Noe/Alex to confirm.
23 return (word >> 24) | ((word << 8) & 0x00FF0000) |
24 ((word >> 8) & 0x0000FF00) | (word << 24);
25 }
26
20 void GetBytesFromUInt32(uint32_t word, char* bytes) { 27 void GetBytesFromUInt32(uint32_t word, char* bytes) {
21 const size_t mask = 0xFF; 28 const size_t mask = 0xFF;
22 bytes[0] = (char)(word & mask); 29 bytes[3] = (char)(word & mask);
Nathan Parker 2016/08/12 23:01:49 Is this ordering endian-dependent as well?
vakh (use Gerrit instead) 2016/08/13 00:15:14 No.
23 bytes[1] = (char)((word >> 8) & mask); 30 bytes[2] = (char)((word >> 8) & mask);
24 bytes[2] = (char)((word >> 16) & mask); 31 bytes[1] = (char)((word >> 16) & mask);
25 bytes[3] = (char)((word >> 24) & mask); 32 bytes[0] = (char)((word >> 24) & mask);
26 } 33 }
27 34
28 } // namespace 35 } // namespace
29 36
30 // static 37 // static
31 V4DecodeResult V4RiceDecoder::ValidateInput(const int32 rice_parameter, 38 V4DecodeResult V4RiceDecoder::ValidateInput(const int32 rice_parameter,
32 const int32 num_entries, 39 const int32 num_entries,
33 const std::string& encoded_data) { 40 const std::string& encoded_data) {
34 if (num_entries < 0) { 41 if (num_entries < 0) {
35 NOTREACHED(); 42 NOTREACHED();
(...skipping 11 matching lines...) Expand all
47 54
48 if (encoded_data.empty()) { 55 if (encoded_data.empty()) {
49 NOTREACHED(); 56 NOTREACHED();
50 return ENCODED_DATA_UNEXPECTED_EMPTY_FAILURE; 57 return ENCODED_DATA_UNEXPECTED_EMPTY_FAILURE;
51 } 58 }
52 59
53 return DECODE_SUCCESS; 60 return DECODE_SUCCESS;
54 } 61 }
55 62
56 // static 63 // static
57 V4DecodeResult V4RiceDecoder::DecodeIntegers(const int32 first_value, 64 V4DecodeResult V4RiceDecoder::DecodeIntegers(const int64 first_value,
58 const int32 rice_parameter, 65 const int32 rice_parameter,
59 const int32 num_entries, 66 const int32 num_entries,
60 const std::string& encoded_data, 67 const std::string& encoded_data,
61 RepeatedField<int32>* out) { 68 RepeatedField<int32>* out) {
62 DCHECK(out); 69 DCHECK(out);
63 70
64 V4DecodeResult result = 71 V4DecodeResult result =
65 ValidateInput(rice_parameter, num_entries, encoded_data); 72 ValidateInput(rice_parameter, num_entries, encoded_data);
66 if (result != DECODE_SUCCESS) { 73 if (result != DECODE_SUCCESS) {
67 return result; 74 return result;
(...skipping 20 matching lines...) Expand all
88 return DECODED_INTEGER_OVERFLOW_FAILURE; 95 return DECODED_INTEGER_OVERFLOW_FAILURE;
89 } 96 }
90 97
91 out->Add(last_value.ValueOrDie()); 98 out->Add(last_value.ValueOrDie());
92 } 99 }
93 100
94 return DECODE_SUCCESS; 101 return DECODE_SUCCESS;
95 } 102 }
96 103
97 // static 104 // static
98 V4DecodeResult V4RiceDecoder::DecodeBytes(const int32 first_value, 105 V4DecodeResult V4RiceDecoder::DecodeBytes(const int64 first_value,
99 const int32 rice_parameter, 106 const int32 rice_parameter,
100 const int32 num_entries, 107 const int32 num_entries,
101 const std::string& encoded_data, 108 const std::string& encoded_data,
102 std::string* out) { 109 std::string* out) {
103 DCHECK(out); 110 DCHECK(out);
104 111
105 V4DecodeResult result = 112 V4DecodeResult result =
106 ValidateInput(rice_parameter, num_entries, encoded_data); 113 ValidateInput(rice_parameter, num_entries, encoded_data);
107 if (result != DECODE_SUCCESS) { 114 if (result != DECODE_SUCCESS) {
108 return result; 115 return result;
109 } 116 }
110 out->reserve((num_entries + 1) * 4); 117 out->reserve((num_entries + 1) * 4);
111 118
112 // Cast to unsigned since we don't look at the sign bit as a sign bit. 119 base::CheckedNumeric<uint32_t> last_value(first_value);
Nathan Parker 2016/08/12 23:01:49 You're casting a int64 to a unit32_t. Is that int
vakh (use Gerrit instead) 2016/08/13 00:15:14 Yes, I am not sure why the first_value is a int64
113 // first_value should have been an unsigned to begin with but proto don't 120 std::set<uint32_t> hash_prefixes;
Nathan Parker 2016/08/12 23:01:49 This is going to use at least another 24 bytes of
vakh (use Gerrit instead) 2016/08/13 00:15:14 Let me try what we discussed offline: use the stri
114 // allow that. 121 hash_prefixes.insert(FlipEndianness(last_value.ValueOrDie()));
115 uint32_t first_value_unsigned = static_cast<uint32_t>(first_value);
116 base::CheckedNumeric<uint32_t> last_value(first_value_unsigned);
117 char bytes[4];
118 GetBytesFromUInt32(last_value.ValueOrDie(), bytes);
119 out->append(bytes, 4);
120 122
121 if (num_entries == 0) { 123 if (num_entries > 0) {
122 return DECODE_SUCCESS; 124 V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data);
125 while (decoder.HasAnotherValue()) {
126 uint32_t offset;
127 result = decoder.GetNextValue(&offset);
128 if (result != DECODE_SUCCESS) {
129 return result;
130 }
131
132 last_value += offset;
133 if (!last_value.IsValid()) {
134 NOTREACHED();
135 return DECODED_INTEGER_OVERFLOW_FAILURE;
136 }
137
138 hash_prefixes.insert(FlipEndianness(last_value.ValueOrDie()));
139 }
123 } 140 }
124 141
125 V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data); 142 char bytes[4];
126 while (decoder.HasAnotherValue()) { 143 for (const uint32_t& hash_prefix : hash_prefixes) {
127 uint32_t offset; 144 GetBytesFromUInt32(hash_prefix, bytes);
128 result = decoder.GetNextValue(&offset);
129 if (result != DECODE_SUCCESS) {
130 return result;
131 }
132
133 last_value += offset;
134 if (!last_value.IsValid()) {
135 NOTREACHED();
136 return DECODED_INTEGER_OVERFLOW_FAILURE;
137 }
138
139 GetBytesFromUInt32(last_value.ValueOrDie(), bytes);
140 out->append(bytes, 4); 145 out->append(bytes, 4);
141 } 146 }
142 147
143 return DECODE_SUCCESS; 148 return DECODE_SUCCESS;
144 } 149 }
145 150
146 V4RiceDecoder::V4RiceDecoder(const int rice_parameter, 151 V4RiceDecoder::V4RiceDecoder(const int rice_parameter,
147 const int num_entries, 152 const int num_entries,
148 const std::string& encoded_data) 153 const std::string& encoded_data)
149 : rice_parameter_(rice_parameter), 154 : rice_parameter_(rice_parameter),
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 return result; 236 return result;
232 } 237 }
233 } 238 }
234 239
235 unsigned int num_bits_left_in_current_word = 240 unsigned int num_bits_left_in_current_word =
236 kMaxBitIndex - current_word_bit_index_; 241 kMaxBitIndex - current_word_bit_index_;
237 if (num_bits_left_in_current_word >= num_requested_bits) { 242 if (num_bits_left_in_current_word >= num_requested_bits) {
238 // All the bits that we need are in |current_word_|. 243 // All the bits that we need are in |current_word_|.
239 GetBitsFromCurrentWord(num_requested_bits, x); 244 GetBitsFromCurrentWord(num_requested_bits, x);
240 } else { 245 } else {
241 // |current_word_| contains fewer bits than we need so we store the current 246 // |current_word_| contains fewer bits than we need so read the remaining
242 // value of |current_word_| in |lower|, then read in a new |current_word_|, 247 // bits from |current_word_| into |lower|, and then call GetNextBits on the
243 // and then pick the remaining bits from the new value of |current_word_|. 248 // remaining number of bits, which will read in a new word into
244 uint32_t lower = current_word_; 249 // |current_word_|.
245 // Bits we need after we read all of |current_word_| 250 uint32_t lower;
251 V4DecodeResult result = GetNextBits(num_bits_left_in_current_word, &lower);
252 if (result != DECODE_SUCCESS) {
253 return result;
254 }
255
246 unsigned int num_bits_from_next_word = 256 unsigned int num_bits_from_next_word =
247 num_requested_bits - num_bits_left_in_current_word; 257 num_requested_bits - num_bits_left_in_current_word;
248 uint32_t upper; 258 uint32_t upper;
249 V4DecodeResult result = GetNextWord(&current_word_); 259 result = GetNextBits(num_bits_from_next_word, &upper);
250 if (result != DECODE_SUCCESS) { 260 if (result != DECODE_SUCCESS) {
251 return result; 261 return result;
252 } 262 }
253 GetBitsFromCurrentWord(num_bits_from_next_word, &upper); 263 *x = (upper << num_bits_left_in_current_word) | lower;
254 *x = (upper << (num_requested_bits - num_bits_from_next_word)) | lower;
255 } 264 }
256 return DECODE_SUCCESS; 265 return DECODE_SUCCESS;
257 } 266 }
258 267
259 void V4RiceDecoder::GetBitsFromCurrentWord(unsigned int num_requested_bits, 268 void V4RiceDecoder::GetBitsFromCurrentWord(unsigned int num_requested_bits,
260 uint32_t* x) { 269 uint32_t* x) {
261 uint32_t mask = 0xFFFFFFFF >> (kMaxBitIndex - num_requested_bits); 270 uint32_t mask = 0xFFFFFFFF >> (kMaxBitIndex - num_requested_bits);
262 *x = current_word_ & mask; 271 *x = current_word_ & mask;
263 current_word_ = current_word_ >> num_requested_bits; 272 current_word_ = current_word_ >> num_requested_bits;
264 current_word_bit_index_ += num_requested_bits; 273 current_word_bit_index_ += num_requested_bits;
(...skipping 11 matching lines...) Expand all
276 bits_read, current_word_, data_byte_index_, current_word_bit_index_, 285 bits_read, current_word_, data_byte_index_, current_word_bit_index_,
277 rice_parameter_); 286 rice_parameter_);
278 } 287 }
279 288
280 std::ostream& operator<<(std::ostream& os, const V4RiceDecoder& rice_decoder) { 289 std::ostream& operator<<(std::ostream& os, const V4RiceDecoder& rice_decoder) {
281 os << rice_decoder.DebugString(); 290 os << rice_decoder.DebugString();
282 return os; 291 return os;
283 } 292 }
284 293
285 } // namespace safe_browsing 294 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698