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

Side by Side Diff: chrome/browser/safe_browsing/prefix_set.cc

Issue 781613002: Make SafeBrowsingDatabase's PrefixSets only updatable by swapping a new one in. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@a2_threadchecks
Patch Set: Created 6 years 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 (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
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 scoped_ptr<const PrefixSet>();
mattm 2014/12/03 23:08:19 can these all be changed to "return nullptr;"?
gab 2014/12/04 20:30:20 Yep :)
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
191 } else if (header.version != kVersion) { 192 } else if (header.version != kVersion) {
192 return scoped_ptr<PrefixSet>(); 193 return scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>();
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 scoped_ptr<const PrefixSet>(
mattm 2014/12/03 23:08:19 does make_scoped_ptr work here?
gab 2014/12/04 20:30:20 Surprisingly, yes :-)! (I expected it to fail as
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/prefix_set.h ('k') | chrome/browser/safe_browsing/prefix_set_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698