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

Side by Side Diff: base/metrics/histogram_samples.cc

Issue 2853853002: Fix overflow when logging MaxInt32 to a sparse histogram. (Closed)
Patch Set: Address comments. Created 3 years, 7 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 | « base/metrics/histogram_samples.h ('k') | base/metrics/persistent_sample_map.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/metrics/histogram_samples.h" 5 #include "base/metrics/histogram_samples.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/numerics/safe_conversions.h"
10 #include "base/numerics/safe_math.h" 11 #include "base/numerics/safe_math.h"
11 #include "base/pickle.h" 12 #include "base/pickle.h"
12 13
13 namespace base { 14 namespace base {
14 15
15 namespace { 16 namespace {
16 17
17 // A shorthand constant for the max value of size_t. 18 // A shorthand constant for the max value of size_t.
18 constexpr size_t kSizeMax = std::numeric_limits<size_t>::max(); 19 constexpr size_t kSizeMax = std::numeric_limits<size_t>::max();
19 20
20 // A constant stored in an AtomicSingleSample (as_atomic) to indicate that the 21 // A constant stored in an AtomicSingleSample (as_atomic) to indicate that the
21 // sample is "disabled" and no further accumulation should be done with it. The 22 // sample is "disabled" and no further accumulation should be done with it. The
22 // value is chosen such that it will be MAX_UINT16 for both |bucket| & |count|, 23 // value is chosen such that it will be MAX_UINT16 for both |bucket| & |count|,
23 // and thus less likely to conflict with real use. Conflicts are explicitly 24 // and thus less likely to conflict with real use. Conflicts are explicitly
24 // handled in the code but it's worth making them as unlikely as possible. 25 // handled in the code but it's worth making them as unlikely as possible.
25 constexpr int32_t kDisabledSingleSample = -1; 26 constexpr int32_t kDisabledSingleSample = -1;
26 27
27 class SampleCountPickleIterator : public SampleCountIterator { 28 class SampleCountPickleIterator : public SampleCountIterator {
28 public: 29 public:
29 explicit SampleCountPickleIterator(PickleIterator* iter); 30 explicit SampleCountPickleIterator(PickleIterator* iter);
30 31
31 bool Done() const override; 32 bool Done() const override;
32 void Next() override; 33 void Next() override;
33 void Get(HistogramBase::Sample* min, 34 void Get(HistogramBase::Sample* min,
34 HistogramBase::Sample* max, 35 int64_t* max,
35 HistogramBase::Count* count) const override; 36 HistogramBase::Count* count) const override;
36 37
37 private: 38 private:
38 PickleIterator* const iter_; 39 PickleIterator* const iter_;
39 40
40 HistogramBase::Sample min_; 41 HistogramBase::Sample min_;
41 HistogramBase::Sample max_; 42 int64_t max_;
42 HistogramBase::Count count_; 43 HistogramBase::Count count_;
43 bool is_done_; 44 bool is_done_;
44 }; 45 };
45 46
46 SampleCountPickleIterator::SampleCountPickleIterator(PickleIterator* iter) 47 SampleCountPickleIterator::SampleCountPickleIterator(PickleIterator* iter)
47 : iter_(iter), 48 : iter_(iter),
48 is_done_(false) { 49 is_done_(false) {
49 Next(); 50 Next();
50 } 51 }
51 52
52 bool SampleCountPickleIterator::Done() const { 53 bool SampleCountPickleIterator::Done() const {
53 return is_done_; 54 return is_done_;
54 } 55 }
55 56
56 void SampleCountPickleIterator::Next() { 57 void SampleCountPickleIterator::Next() {
57 DCHECK(!Done()); 58 DCHECK(!Done());
58 if (!iter_->ReadInt(&min_) || 59 if (!iter_->ReadInt(&min_) || !iter_->ReadInt64(&max_) ||
59 !iter_->ReadInt(&max_) || 60 !iter_->ReadInt(&count_)) {
60 !iter_->ReadInt(&count_))
61 is_done_ = true; 61 is_done_ = true;
62 }
62 } 63 }
63 64
64 void SampleCountPickleIterator::Get(HistogramBase::Sample* min, 65 void SampleCountPickleIterator::Get(HistogramBase::Sample* min,
65 HistogramBase::Sample* max, 66 int64_t* max,
66 HistogramBase::Count* count) const { 67 HistogramBase::Count* count) const {
67 DCHECK(!Done()); 68 DCHECK(!Done());
68 *min = min_; 69 *min = min_;
69 *max = max_; 70 *max = max_;
70 *count = count_; 71 *count = count_;
71 } 72 }
72 73
73 } // namespace 74 } // namespace
74 75
75 static_assert(sizeof(HistogramSamples::AtomicSingleSample) == 76 static_assert(sizeof(HistogramSamples::AtomicSingleSample) ==
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 DCHECK(success); 214 DCHECK(success);
214 } 215 }
215 216
216 bool HistogramSamples::Serialize(Pickle* pickle) const { 217 bool HistogramSamples::Serialize(Pickle* pickle) const {
217 if (!pickle->WriteInt64(sum())) 218 if (!pickle->WriteInt64(sum()))
218 return false; 219 return false;
219 if (!pickle->WriteInt(redundant_count())) 220 if (!pickle->WriteInt(redundant_count()))
220 return false; 221 return false;
221 222
222 HistogramBase::Sample min; 223 HistogramBase::Sample min;
223 HistogramBase::Sample max; 224 int64_t max;
224 HistogramBase::Count count; 225 HistogramBase::Count count;
225 for (std::unique_ptr<SampleCountIterator> it = Iterator(); !it->Done(); 226 for (std::unique_ptr<SampleCountIterator> it = Iterator(); !it->Done();
226 it->Next()) { 227 it->Next()) {
227 it->Get(&min, &max, &count); 228 it->Get(&min, &max, &count);
228 if (!pickle->WriteInt(min) || 229 if (!pickle->WriteInt(min) || !pickle->WriteInt64(max) ||
229 !pickle->WriteInt(max) || 230 !pickle->WriteInt(count)) {
230 !pickle->WriteInt(count))
231 return false; 231 return false;
232 }
232 } 233 }
233 return true; 234 return true;
234 } 235 }
235 236
236 bool HistogramSamples::AccumulateSingleSample(HistogramBase::Sample value, 237 bool HistogramSamples::AccumulateSingleSample(HistogramBase::Sample value,
237 HistogramBase::Count count, 238 HistogramBase::Count count,
238 size_t bucket) { 239 size_t bucket) {
239 if (single_sample().Accumulate(bucket, count)) { 240 if (single_sample().Accumulate(bucket, count)) {
240 // Success. Update the (separate) sum and redundant-count. 241 // Success. Update the (separate) sum and redundant-count.
241 IncreaseSumAndCount(static_cast<int64_t>(value) * count, count); 242 IncreaseSumAndCount(strict_cast<int64_t>(value) * count, count);
242 return true; 243 return true;
243 } 244 }
244 return false; 245 return false;
245 } 246 }
246 247
247 void HistogramSamples::IncreaseSumAndCount(int64_t sum, 248 void HistogramSamples::IncreaseSumAndCount(int64_t sum,
248 HistogramBase::Count count) { 249 HistogramBase::Count count) {
249 #ifdef ARCH_CPU_64_BITS 250 #ifdef ARCH_CPU_64_BITS
250 subtle::NoBarrier_AtomicIncrement(&meta_->sum, sum); 251 subtle::NoBarrier_AtomicIncrement(&meta_->sum, sum);
251 #else 252 #else
252 meta_->sum += sum; 253 meta_->sum += sum;
253 #endif 254 #endif
254 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, count); 255 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, count);
255 } 256 }
256 257
257 SampleCountIterator::~SampleCountIterator() {} 258 SampleCountIterator::~SampleCountIterator() {}
258 259
259 bool SampleCountIterator::GetBucketIndex(size_t* index) const { 260 bool SampleCountIterator::GetBucketIndex(size_t* index) const {
260 DCHECK(!Done()); 261 DCHECK(!Done());
261 return false; 262 return false;
262 } 263 }
263 264
264 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min, 265 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min,
265 HistogramBase::Sample max, 266 int64_t max,
266 HistogramBase::Count count) 267 HistogramBase::Count count)
267 : SingleSampleIterator(min, max, count, kSizeMax) {} 268 : SingleSampleIterator(min, max, count, kSizeMax) {}
268 269
269 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min, 270 SingleSampleIterator::SingleSampleIterator(HistogramBase::Sample min,
270 HistogramBase::Sample max, 271 int64_t max,
271 HistogramBase::Count count, 272 HistogramBase::Count count,
272 size_t bucket_index) 273 size_t bucket_index)
273 : min_(min), max_(max), bucket_index_(bucket_index), count_(count) {} 274 : min_(min), max_(max), bucket_index_(bucket_index), count_(count) {}
274 275
275 SingleSampleIterator::~SingleSampleIterator() {} 276 SingleSampleIterator::~SingleSampleIterator() {}
276 277
277 bool SingleSampleIterator::Done() const { 278 bool SingleSampleIterator::Done() const {
278 return count_ == 0; 279 return count_ == 0;
279 } 280 }
280 281
281 void SingleSampleIterator::Next() { 282 void SingleSampleIterator::Next() {
282 DCHECK(!Done()); 283 DCHECK(!Done());
283 count_ = 0; 284 count_ = 0;
284 } 285 }
285 286
286 void SingleSampleIterator::Get(HistogramBase::Sample* min, 287 void SingleSampleIterator::Get(HistogramBase::Sample* min,
287 HistogramBase::Sample* max, 288 int64_t* max,
288 HistogramBase::Count* count) const { 289 HistogramBase::Count* count) const {
289 DCHECK(!Done()); 290 DCHECK(!Done());
290 if (min != nullptr) 291 if (min != nullptr)
291 *min = min_; 292 *min = min_;
292 if (max != nullptr) 293 if (max != nullptr)
293 *max = max_; 294 *max = max_;
294 if (count != nullptr) 295 if (count != nullptr)
295 *count = count_; 296 *count = count_;
296 } 297 }
297 298
298 bool SingleSampleIterator::GetBucketIndex(size_t* index) const { 299 bool SingleSampleIterator::GetBucketIndex(size_t* index) const {
299 DCHECK(!Done()); 300 DCHECK(!Done());
300 if (bucket_index_ == kSizeMax) 301 if (bucket_index_ == kSizeMax)
301 return false; 302 return false;
302 *index = bucket_index_; 303 *index = bucket_index_;
303 return true; 304 return true;
304 } 305 }
305 306
306 } // namespace base 307 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/histogram_samples.h ('k') | base/metrics/persistent_sample_map.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698