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

Side by Side Diff: net/base/backoff_entry.cc

Issue 1039263003: Prevent integer overflow when (de)serializing BackoffEntry Base URL: https://chromium.googlesource.com/chromium/src.git@backoff
Patch Set: Created 5 years, 8 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 | « no previous file | net/base/backoff_entry_unittest.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 "net/base/backoff_entry.h" 5 #include "net/base/backoff_entry.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 10
11 #include "base/basictypes.h" 11 #include "base/basictypes.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/numerics/safe_math.h" 13 #include "base/numerics/safe_math.h"
14 #include "base/rand_util.h" 14 #include "base/rand_util.h"
15 #include "base/strings/string_number_conversions.h"
15 #include "base/values.h" 16 #include "base/values.h"
16 17
17 namespace net { 18 namespace net {
18 19
19 BackoffEntry::BackoffEntry(const BackoffEntry::Policy* const policy) 20 BackoffEntry::BackoffEntry(const BackoffEntry::Policy* const policy)
20 : policy_(policy) { 21 : policy_(policy) {
21 DCHECK(policy_); 22 DCHECK(policy_);
22 Reset(); 23 Reset();
23 } 24 }
24 25
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 // We leave exponential_backoff_release_time_ unset, meaning 0. We could 109 // We leave exponential_backoff_release_time_ unset, meaning 0. We could
109 // initialize to ImplGetTimeNow() but because it's a virtual method it's 110 // initialize to ImplGetTimeNow() but because it's a virtual method it's
110 // not safe to call in the constructor (and the constructor calls Reset()). 111 // not safe to call in the constructor (and the constructor calls Reset()).
111 // The effects are the same, i.e. ShouldRejectRequest() will return false 112 // The effects are the same, i.e. ShouldRejectRequest() will return false
112 // right after Reset(). 113 // right after Reset().
113 exponential_backoff_release_time_ = base::TimeTicks(); 114 exponential_backoff_release_time_ = base::TimeTicks();
114 } 115 }
115 116
116 scoped_ptr<base::ListValue> BackoffEntry::Serialize() const { 117 scoped_ptr<base::ListValue> BackoffEntry::Serialize() const {
117 scoped_ptr<base::ListValue> serialized(new base::ListValue()); 118 scoped_ptr<base::ListValue> serialized(new base::ListValue());
119 const int64 time_ticks_now_us =
120 (ImplGetTimeNow() - base::TimeTicks()).InMicroseconds();
121 const int64 wall_clock_time_now_us =
122 (ImplGetWallClockTimeNow() - base::Time()).InMicroseconds();
123 // Do overflow checking in microseconds, the internal unit of TimeTicks, Time
124 // and TimeDelta.
125 base::internal::CheckedNumeric<int64> time_until_release_us =
126 (GetReleaseTime() - base::TimeTicks()).InMicroseconds();
127 time_until_release_us -= time_ticks_now_us;
128 base::internal::CheckedNumeric<int64> wall_clock_release_time_us =
129 time_until_release_us.ValueOrDefault(kint64min);
130 wall_clock_release_time_us += wall_clock_time_now_us;
131 serialized->AppendString(base::Int64ToString(
132 wall_clock_release_time_us.ValueOrDefault(kint64max)));
118 serialized->AppendInteger(failure_count_); 133 serialized->AppendInteger(failure_count_);
119 base::Time absolute_release_time =
120 (GetReleaseTime() - ImplGetTimeNow()) + ImplGetWallClockTimeNow();
121 serialized->AppendDouble(absolute_release_time.ToDoubleT());
122 return serialized; 134 return serialized;
123 } 135 }
124 136
125 bool BackoffEntry::Deserialize(const base::ListValue& serialized) { 137 bool BackoffEntry::Deserialize(const base::ListValue& serialized) {
126 if (serialized.GetSize() != 2) 138 if (serialized.GetSize() != 2)
127 return false; 139 return false;
140 std::string wall_clock_release_time_string;
141 if (!serialized.GetString(0, &wall_clock_release_time_string))
142 return false;
143 int64 wall_clock_release_time_us;
144 if (!base::StringToInt64(wall_clock_release_time_string,
145 &wall_clock_release_time_us))
146 return false;
128 int failure_count; 147 int failure_count;
129 if (!serialized.GetInteger(0, &failure_count)) 148 if (!serialized.GetInteger(1, &failure_count))
130 return false; 149 return false;
131 double absolute_release_time_double; 150 const int64 wall_clock_time_now_us =
132 if (!serialized.GetDouble(1, &absolute_release_time_double)) 151 (ImplGetWallClockTimeNow() - base::Time()).InMicroseconds();
133 return false; 152 base::internal::CheckedNumeric<int64> time_until_release_us =
153 wall_clock_release_time_us;
154 time_until_release_us -= wall_clock_time_now_us;
155 exponential_backoff_release_time_ =
156 TimeUntilReleaseToReleaseTime(base::TimeDelta::FromMicroseconds(
157 time_until_release_us.ValueOrDefault(kint64min)));
134 failure_count_ = failure_count; 158 failure_count_ = failure_count;
135 base::Time absolute_release_time =
136 base::Time::FromDoubleT(absolute_release_time_double);
137 base::TimeDelta time_until_release =
138 absolute_release_time - ImplGetWallClockTimeNow();
139 exponential_backoff_release_time_ =
140 TimeUntilReleaseToReleaseTime(time_until_release);
141 return true; 159 return true;
142 } 160 }
143 161
144 base::TimeTicks BackoffEntry::ImplGetTimeNow() const { 162 base::TimeTicks BackoffEntry::ImplGetTimeNow() const {
145 return base::TimeTicks::Now(); 163 return base::TimeTicks::Now();
146 } 164 }
147 165
148 base::Time BackoffEntry::ImplGetWallClockTimeNow() const { 166 base::Time BackoffEntry::ImplGetWallClockTimeNow() const {
149 return base::Time::Now(); 167 return base::Time::Now();
150 } 168 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // Decide between maximum release time and calculated release time, accounting 225 // Decide between maximum release time and calculated release time, accounting
208 // for overflow with both. 226 // for overflow with both.
209 int64 release_time_us = std::min( 227 int64 release_time_us = std::min(
210 calculated_release_time_us.ValueOrDefault(kint64max), 228 calculated_release_time_us.ValueOrDefault(kint64max),
211 maximum_release_time_us.ValueOrDefault(kint64max)); 229 maximum_release_time_us.ValueOrDefault(kint64max));
212 230
213 return base::TimeTicks() + base::TimeDelta::FromMicroseconds(release_time_us); 231 return base::TimeTicks() + base::TimeDelta::FromMicroseconds(release_time_us);
214 } 232 }
215 233
216 } // namespace net 234 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/base/backoff_entry_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698