OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/safe_browsing/prefix_set.h" | 5 #include "chrome/browser/safe_browsing/prefix_set.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
10 #include "base/files/scoped_file.h" | 10 #include "base/files/scoped_file.h" |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 SBPrefix current = index_[ii].first; | 150 SBPrefix current = index_[ii].first; |
151 prefixes->push_back(current); | 151 prefixes->push_back(current); |
152 for (size_t di = index_[ii].second; di < deltas_end; ++di) { | 152 for (size_t di = index_[ii].second; di < deltas_end; ++di) { |
153 current += deltas_[di]; | 153 current += deltas_[di]; |
154 prefixes->push_back(current); | 154 prefixes->push_back(current); |
155 } | 155 } |
156 } | 156 } |
157 } | 157 } |
158 | 158 |
159 // static | 159 // static |
160 scoped_ptr<PrefixSet> PrefixSet::LoadFile(const base::FilePath& filter_name) { | 160 scoped_ptr<const PrefixSet> PrefixSet::LoadFile( |
| 161 const base::FilePath& filter_name) { |
161 int64 size_64; | 162 int64 size_64; |
162 if (!base::GetFileSize(filter_name, &size_64)) | 163 if (!base::GetFileSize(filter_name, &size_64)) |
163 return scoped_ptr<PrefixSet>(); | 164 return nullptr; |
164 using base::MD5Digest; | 165 using base::MD5Digest; |
165 if (size_64 < static_cast<int64>(sizeof(FileHeader) + sizeof(MD5Digest))) | 166 if (size_64 < static_cast<int64>(sizeof(FileHeader) + sizeof(MD5Digest))) |
166 return scoped_ptr<PrefixSet>(); | 167 return nullptr; |
167 | 168 |
168 base::ScopedFILE file(base::OpenFile(filter_name, "rb")); | 169 base::ScopedFILE file(base::OpenFile(filter_name, "rb")); |
169 if (!file.get()) | 170 if (!file.get()) |
170 return scoped_ptr<PrefixSet>(); | 171 return nullptr; |
171 | 172 |
172 FileHeader header; | 173 FileHeader header; |
173 size_t read = fread(&header, sizeof(header), 1, file.get()); | 174 size_t read = fread(&header, sizeof(header), 1, file.get()); |
174 if (read != 1) | 175 if (read != 1) |
175 return scoped_ptr<PrefixSet>(); | 176 return nullptr; |
176 | 177 |
177 // The file looks valid, start building the digest. | 178 // The file looks valid, start building the digest. |
178 base::MD5Context context; | 179 base::MD5Context context; |
179 base::MD5Init(&context); | 180 base::MD5Init(&context); |
180 base::MD5Update(&context, base::StringPiece(reinterpret_cast<char*>(&header), | 181 base::MD5Update(&context, base::StringPiece(reinterpret_cast<char*>(&header), |
181 sizeof(header))); | 182 sizeof(header))); |
182 | 183 |
183 if (header.magic != kMagic) | 184 if (header.magic != kMagic) |
184 return scoped_ptr<PrefixSet>(); | 185 return nullptr; |
185 | 186 |
186 // Track version read to inform removal of support for older versions. | 187 // Track version read to inform removal of support for older versions. |
187 UMA_HISTOGRAM_SPARSE_SLOWLY("SB2.PrefixSetVersionRead", header.version); | 188 UMA_HISTOGRAM_SPARSE_SLOWLY("SB2.PrefixSetVersionRead", header.version); |
188 | 189 |
189 if (header.version <= kDeprecatedVersion) { | 190 if (header.version <= kDeprecatedVersion) { |
190 return scoped_ptr<PrefixSet>(); | 191 return nullptr; |
191 } else if (header.version != kVersion) { | 192 } else if (header.version != kVersion) { |
192 return scoped_ptr<PrefixSet>(); | 193 return nullptr; |
193 } | 194 } |
194 | 195 |
195 IndexVector index; | 196 IndexVector index; |
196 const size_t index_bytes = sizeof(index[0]) * header.index_size; | 197 const size_t index_bytes = sizeof(index[0]) * header.index_size; |
197 | 198 |
198 std::vector<uint16> deltas; | 199 std::vector<uint16> deltas; |
199 const size_t deltas_bytes = sizeof(deltas[0]) * header.deltas_size; | 200 const size_t deltas_bytes = sizeof(deltas[0]) * header.deltas_size; |
200 | 201 |
201 std::vector<SBFullHash> full_hashes; | 202 std::vector<SBFullHash> full_hashes; |
202 const size_t full_hashes_bytes = | 203 const size_t full_hashes_bytes = |
203 sizeof(full_hashes[0]) * header.full_hashes_size; | 204 sizeof(full_hashes[0]) * header.full_hashes_size; |
204 | 205 |
205 // Check for bogus sizes before allocating any space. | 206 // Check for bogus sizes before allocating any space. |
206 const size_t expected_bytes = sizeof(header) + | 207 const size_t expected_bytes = sizeof(header) + |
207 index_bytes + deltas_bytes + full_hashes_bytes + sizeof(MD5Digest); | 208 index_bytes + deltas_bytes + full_hashes_bytes + sizeof(MD5Digest); |
208 if (static_cast<int64>(expected_bytes) != size_64) | 209 if (static_cast<int64>(expected_bytes) != size_64) |
209 return scoped_ptr<PrefixSet>(); | 210 return nullptr; |
210 | 211 |
211 // Read the index vector. Herb Sutter indicates that vectors are | 212 // Read the index vector. Herb Sutter indicates that vectors are |
212 // guaranteed to be contiuguous, so reading to where element 0 lives | 213 // guaranteed to be contiuguous, so reading to where element 0 lives |
213 // is valid. | 214 // is valid. |
214 if (header.index_size) { | 215 if (header.index_size) { |
215 index.resize(header.index_size); | 216 index.resize(header.index_size); |
216 read = fread(&(index[0]), sizeof(index[0]), index.size(), file.get()); | 217 read = fread(&(index[0]), sizeof(index[0]), index.size(), file.get()); |
217 if (read != index.size()) | 218 if (read != index.size()) |
218 return scoped_ptr<PrefixSet>(); | 219 return nullptr; |
219 base::MD5Update(&context, | 220 base::MD5Update(&context, |
220 base::StringPiece(reinterpret_cast<char*>(&(index[0])), | 221 base::StringPiece(reinterpret_cast<char*>(&(index[0])), |
221 index_bytes)); | 222 index_bytes)); |
222 } | 223 } |
223 | 224 |
224 // Read vector of deltas. | 225 // Read vector of deltas. |
225 if (header.deltas_size) { | 226 if (header.deltas_size) { |
226 deltas.resize(header.deltas_size); | 227 deltas.resize(header.deltas_size); |
227 read = fread(&(deltas[0]), sizeof(deltas[0]), deltas.size(), file.get()); | 228 read = fread(&(deltas[0]), sizeof(deltas[0]), deltas.size(), file.get()); |
228 if (read != deltas.size()) | 229 if (read != deltas.size()) |
229 return scoped_ptr<PrefixSet>(); | 230 return nullptr; |
230 base::MD5Update(&context, | 231 base::MD5Update(&context, |
231 base::StringPiece(reinterpret_cast<char*>(&(deltas[0])), | 232 base::StringPiece(reinterpret_cast<char*>(&(deltas[0])), |
232 deltas_bytes)); | 233 deltas_bytes)); |
233 } | 234 } |
234 | 235 |
235 // Read vector of full hashes. | 236 // Read vector of full hashes. |
236 if (header.full_hashes_size) { | 237 if (header.full_hashes_size) { |
237 full_hashes.resize(header.full_hashes_size); | 238 full_hashes.resize(header.full_hashes_size); |
238 read = fread(&(full_hashes[0]), sizeof(full_hashes[0]), full_hashes.size(), | 239 read = fread(&(full_hashes[0]), sizeof(full_hashes[0]), full_hashes.size(), |
239 file.get()); | 240 file.get()); |
240 if (read != full_hashes.size()) | 241 if (read != full_hashes.size()) |
241 return scoped_ptr<PrefixSet>(); | 242 return nullptr; |
242 base::MD5Update(&context, | 243 base::MD5Update(&context, |
243 base::StringPiece( | 244 base::StringPiece( |
244 reinterpret_cast<char*>(&(full_hashes[0])), | 245 reinterpret_cast<char*>(&(full_hashes[0])), |
245 full_hashes_bytes)); | 246 full_hashes_bytes)); |
246 } | 247 } |
247 | 248 |
248 base::MD5Digest calculated_digest; | 249 base::MD5Digest calculated_digest; |
249 base::MD5Final(&calculated_digest, &context); | 250 base::MD5Final(&calculated_digest, &context); |
250 | 251 |
251 base::MD5Digest file_digest; | 252 base::MD5Digest file_digest; |
252 read = fread(&file_digest, sizeof(file_digest), 1, file.get()); | 253 read = fread(&file_digest, sizeof(file_digest), 1, file.get()); |
253 if (read != 1) | 254 if (read != 1) |
254 return scoped_ptr<PrefixSet>(); | 255 return nullptr; |
255 | 256 |
256 if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) | 257 if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) |
257 return scoped_ptr<PrefixSet>(); | 258 return nullptr; |
258 | 259 |
259 // Steals vector contents using swap(). | 260 // Steals vector contents using swap(). |
260 return scoped_ptr<PrefixSet>(new PrefixSet(&index, &deltas, &full_hashes)); | 261 return make_scoped_ptr( |
| 262 new PrefixSet(&index, &deltas, &full_hashes)); |
261 } | 263 } |
262 | 264 |
263 bool PrefixSet::WriteFile(const base::FilePath& filter_name) const { | 265 bool PrefixSet::WriteFile(const base::FilePath& filter_name) const { |
264 FileHeader header; | 266 FileHeader header; |
265 header.magic = kMagic; | 267 header.magic = kMagic; |
266 header.version = kVersion; | 268 header.version = kVersion; |
267 header.index_size = static_cast<uint32>(index_.size()); | 269 header.index_size = static_cast<uint32>(index_.size()); |
268 header.deltas_size = static_cast<uint32>(deltas_.size()); | 270 header.deltas_size = static_cast<uint32>(deltas_.size()); |
269 header.full_hashes_size = static_cast<uint32>(full_hashes_.size()); | 271 header.full_hashes_size = static_cast<uint32>(full_hashes_.size()); |
270 | 272 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 PrefixSetBuilder::PrefixSetBuilder(const std::vector<SBPrefix>& prefixes) | 364 PrefixSetBuilder::PrefixSetBuilder(const std::vector<SBPrefix>& prefixes) |
363 : prefix_set_(new PrefixSet()) { | 365 : prefix_set_(new PrefixSet()) { |
364 for (size_t i = 0; i < prefixes.size(); ++i) { | 366 for (size_t i = 0; i < prefixes.size(); ++i) { |
365 AddPrefix(prefixes[i]); | 367 AddPrefix(prefixes[i]); |
366 } | 368 } |
367 } | 369 } |
368 | 370 |
369 PrefixSetBuilder::~PrefixSetBuilder() { | 371 PrefixSetBuilder::~PrefixSetBuilder() { |
370 } | 372 } |
371 | 373 |
372 scoped_ptr<PrefixSet> PrefixSetBuilder::GetPrefixSet( | 374 scoped_ptr<const PrefixSet> PrefixSetBuilder::GetPrefixSet( |
373 const std::vector<SBFullHash>& hashes) { | 375 const std::vector<SBFullHash>& hashes) { |
374 DCHECK(prefix_set_.get()); | 376 DCHECK(prefix_set_.get()); |
375 | 377 |
376 // Flush runs until buffered data is gone. | 378 // Flush runs until buffered data is gone. |
377 while (!buffer_.empty()) { | 379 while (!buffer_.empty()) { |
378 EmitRun(); | 380 EmitRun(); |
379 } | 381 } |
380 | 382 |
381 // Precisely size |index_| for read-only. It's 50k-60k, so minor savings, but | 383 // Precisely size |index_| for read-only. It's 50k-60k, so minor savings, but |
382 // they're almost free. | 384 // they're almost free. |
383 PrefixSet::IndexVector(prefix_set_->index_).swap(prefix_set_->index_); | 385 PrefixSet::IndexVector(prefix_set_->index_).swap(prefix_set_->index_); |
384 | 386 |
385 prefix_set_->full_hashes_ = hashes; | 387 prefix_set_->full_hashes_ = hashes; |
386 std::sort(prefix_set_->full_hashes_.begin(), prefix_set_->full_hashes_.end(), | 388 std::sort(prefix_set_->full_hashes_.begin(), prefix_set_->full_hashes_.end(), |
387 SBFullHashLess); | 389 SBFullHashLess); |
388 | 390 |
389 return prefix_set_.Pass(); | 391 return prefix_set_.Pass(); |
390 } | 392 } |
391 | 393 |
392 scoped_ptr<PrefixSet> PrefixSetBuilder::GetPrefixSetNoHashes() { | 394 scoped_ptr<const PrefixSet> PrefixSetBuilder::GetPrefixSetNoHashes() { |
393 return GetPrefixSet(std::vector<SBFullHash>()).Pass(); | 395 return GetPrefixSet(std::vector<SBFullHash>()).Pass(); |
394 } | 396 } |
395 | 397 |
396 void PrefixSetBuilder::EmitRun() { | 398 void PrefixSetBuilder::EmitRun() { |
397 DCHECK(prefix_set_.get()); | 399 DCHECK(prefix_set_.get()); |
398 | 400 |
399 SBPrefix prev_prefix = buffer_[0]; | 401 SBPrefix prev_prefix = buffer_[0]; |
400 uint16 run[PrefixSet::kMaxRun]; | 402 uint16 run[PrefixSet::kMaxRun]; |
401 size_t run_pos = 0; | 403 size_t run_pos = 0; |
402 | 404 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 } | 439 } |
438 buffer_.push_back(prefix); | 440 buffer_.push_back(prefix); |
439 | 441 |
440 // Flush buffer when a run can be constructed. +1 for the index item, and +1 | 442 // Flush buffer when a run can be constructed. +1 for the index item, and +1 |
441 // to leave at least one item in the buffer for dropping duplicates. | 443 // to leave at least one item in the buffer for dropping duplicates. |
442 if (buffer_.size() > PrefixSet::kMaxRun + 2) | 444 if (buffer_.size() > PrefixSet::kMaxRun + 2) |
443 EmitRun(); | 445 EmitRun(); |
444 } | 446 } |
445 | 447 |
446 } // namespace safe_browsing | 448 } // namespace safe_browsing |
OLD | NEW |