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

Side by Side Diff: base/numerics/safe_math_impl.h

Issue 2440143003: Fix some lurking div by 0s in safe_math_impl.h (Closed)
Patch Set: Created 4 years, 1 month 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 | base/numerics/safe_numerics_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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_ 5 #ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_
6 #define BASE_NUMERICS_SAFE_MATH_IMPL_H_ 6 #define BASE_NUMERICS_SAFE_MATH_IMPL_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 template <typename T> 198 template <typename T>
199 typename std::enable_if<std::numeric_limits<T>::is_integer && 199 typename std::enable_if<std::numeric_limits<T>::is_integer &&
200 std::numeric_limits<T>::is_signed && 200 std::numeric_limits<T>::is_signed &&
201 (sizeof(T) * 2 > sizeof(uintmax_t)), 201 (sizeof(T) * 2 > sizeof(uintmax_t)),
202 T>::type 202 T>::type
203 CheckedMul(T x, T y, RangeConstraint* validity) { 203 CheckedMul(T x, T y, RangeConstraint* validity) {
204 // If either side is zero then the result will be zero. 204 // If either side is zero then the result will be zero.
205 if (!x || !y) { 205 if (!x || !y) {
206 *validity = RANGE_VALID; 206 *validity = RANGE_VALID;
207 return static_cast<T>(0); 207 return static_cast<T>(0);
208 208 }
209 } else if (x > 0) { 209 if (x > 0) {
210 if (y > 0) 210 if (y > 0) {
211 *validity = 211 *validity =
212 x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW; 212 x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW;
213 else 213 } else {
214 *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID 214 *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID
215 : RANGE_UNDERFLOW; 215 : RANGE_UNDERFLOW;
216 216 }
217 } else { 217 } else {
218 if (y > 0) 218 if (y > 0) {
219 *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID 219 *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID
220 : RANGE_UNDERFLOW; 220 : RANGE_UNDERFLOW;
221 else 221 } else {
222 *validity = 222 *validity =
223 y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; 223 y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW;
224 }
224 } 225 }
jschuh 2016/11/01 17:21:55 Could you move this out to another CL, since it's
225
226 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0); 226 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0);
227 } 227 }
228 228
229 template <typename T> 229 template <typename T>
230 typename std::enable_if<std::numeric_limits<T>::is_integer && 230 typename std::enable_if<std::numeric_limits<T>::is_integer &&
231 !std::numeric_limits<T>::is_signed && 231 !std::numeric_limits<T>::is_signed &&
232 (sizeof(T) * 2 > sizeof(uintmax_t)), 232 (sizeof(T) * 2 > sizeof(uintmax_t)),
233 T>::type 233 T>::type
234 CheckedMul(T x, T y, RangeConstraint* validity) { 234 CheckedMul(T x, T y, RangeConstraint* validity) {
235 *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) 235 *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y)
236 ? RANGE_VALID 236 ? RANGE_VALID
237 : RANGE_OVERFLOW; 237 : RANGE_OVERFLOW;
238 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0); 238 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0);
239 } 239 }
240 240
241 // Division just requires a check for an invalid negation on signed min/-1. 241 // Division just requires a check for a zero denominator or an invalid negation
242 // on signed min/-1.
242 template <typename T> 243 template <typename T>
243 T CheckedDiv(T x, 244 T CheckedDiv(T x,
244 T y, 245 T y,
245 RangeConstraint* validity, 246 RangeConstraint* validity,
246 typename std::enable_if<std::numeric_limits<T>::is_integer, 247 typename std::enable_if<std::numeric_limits<T>::is_integer,
247 int>::type = 0) { 248 int>::type = 0) {
249 if (y == 0) {
250 *validity = RANGE_INVALID;
251 return static_cast<T>(0);
252 }
248 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && 253 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() &&
249 y == static_cast<T>(-1)) { 254 y == static_cast<T>(-1)) {
250 *validity = RANGE_OVERFLOW; 255 *validity = RANGE_OVERFLOW;
251 return std::numeric_limits<T>::min(); 256 return std::numeric_limits<T>::min();
252 } 257 }
253 258
254 *validity = RANGE_VALID; 259 *validity = RANGE_VALID;
255 return static_cast<T>(x / y); 260 return static_cast<T>(x / y);
256 } 261 }
257 262
258 template <typename T> 263 template <typename T>
259 typename std::enable_if<std::numeric_limits<T>::is_integer && 264 typename std::enable_if<std::numeric_limits<T>::is_integer &&
260 std::numeric_limits<T>::is_signed, 265 std::numeric_limits<T>::is_signed,
261 T>::type 266 T>::type
262 CheckedMod(T x, T y, RangeConstraint* validity) { 267 CheckedMod(T x, T y, RangeConstraint* validity) {
263 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; 268 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID;
264 return static_cast<T>(*validity == RANGE_VALID ? x % y: 0); 269 return static_cast<T>(*validity == RANGE_VALID ? x % y: 0);
265 } 270 }
266 271
267 template <typename T> 272 template <typename T>
268 typename std::enable_if<std::numeric_limits<T>::is_integer && 273 typename std::enable_if<std::numeric_limits<T>::is_integer &&
269 !std::numeric_limits<T>::is_signed, 274 !std::numeric_limits<T>::is_signed,
270 T>::type 275 T>::type
271 CheckedMod(T x, T y, RangeConstraint* validity) { 276 CheckedMod(T x, T y, RangeConstraint* validity) {
272 *validity = RANGE_VALID; 277 *validity = y != 0 ? RANGE_VALID : RANGE_INVALID;
273 return static_cast<T>(x % y); 278 return static_cast<T>(*validity == RANGE_VALID ? x % y: 0);
274 } 279 }
275 280
276 template <typename T> 281 template <typename T>
277 typename std::enable_if<std::numeric_limits<T>::is_integer && 282 typename std::enable_if<std::numeric_limits<T>::is_integer &&
278 std::numeric_limits<T>::is_signed, 283 std::numeric_limits<T>::is_signed,
279 T>::type 284 T>::type
280 CheckedNeg(T value, RangeConstraint* validity) { 285 CheckedNeg(T value, RangeConstraint* validity) {
281 *validity = 286 *validity =
282 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; 287 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
283 // The negation of signed min is min, so catch that one. 288 // The negation of signed min is min, so catch that one.
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 sizeof(T) >= (2 * sizeof(Lhs)) && 528 sizeof(T) >= (2 * sizeof(Lhs)) &&
524 StaticDstRangeRelationToSrcRange<T, Rhs>::value != 529 StaticDstRangeRelationToSrcRange<T, Rhs>::value !=
525 NUMERIC_RANGE_CONTAINED && 530 NUMERIC_RANGE_CONTAINED &&
526 sizeof(T) >= (2 * sizeof(Rhs)); 531 sizeof(T) >= (2 * sizeof(Rhs));
527 }; 532 };
528 533
529 } // namespace internal 534 } // namespace internal
530 } // namespace base 535 } // namespace base
531 536
532 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ 537 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_
OLDNEW
« no previous file with comments | « no previous file | base/numerics/safe_numerics_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698