| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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_CHECKED_MATH_H_ | 5 #ifndef BASE_NUMERICS_CHECKED_MATH_H_ |
| 6 #define BASE_NUMERICS_CHECKED_MATH_H_ | 6 #define BASE_NUMERICS_CHECKED_MATH_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| 11 #include <type_traits> | 11 #include <type_traits> |
| 12 | 12 |
| 13 #include "base/numerics/checked_math_impl.h" | 13 #include "base/numerics/checked_math_impl.h" |
| 14 | 14 |
| 15 namespace base { | 15 namespace base { |
| 16 namespace internal { | 16 namespace internal { |
| 17 | 17 |
| 18 // CheckedNumeric<> implements all the logic and operators for detecting integer | |
| 19 // boundary conditions such as overflow, underflow, and invalid conversions. | |
| 20 // The CheckedNumeric type implicitly converts from floating point and integer | |
| 21 // data types, and contains overloads for basic arithmetic operations (i.e.: +, | |
| 22 // -, *, / for all types and %, <<, >>, &, |, ^ for integers). Type promotions | |
| 23 // are a slightly modified version of the standard C arithmetic rules with the | |
| 24 // two differences being that there is no default promotion to int and bitwise | |
| 25 // logical operations always return an unsigned of the wider type. | |
| 26 // | |
| 27 // You may also use one of the variadic convenience functions, which accept | |
| 28 // standard arithmetic or CheckedNumeric types, perform arithmetic operations, | |
| 29 // and return a CheckedNumeric result. The supported functions are: | |
| 30 // CheckAdd() - Addition. | |
| 31 // CheckSub() - Subtraction. | |
| 32 // CheckMul() - Multiplication. | |
| 33 // CheckDiv() - Division. | |
| 34 // CheckMod() - Modulous (integer only). | |
| 35 // CheckLsh() - Left integer shift (integer only). | |
| 36 // CheckRsh() - Right integer shift (integer only). | |
| 37 // CheckAnd() - Bitwise AND (integer only with unsigned result). | |
| 38 // CheckOr() - Bitwise OR (integer only with unsigned result). | |
| 39 // CheckXor() - Bitwise XOR (integer only with unsigned result). | |
| 40 // CheckMax() - Maximum of supplied arguments. | |
| 41 // CheckMin() - Minimum of supplied arguments. | |
| 42 // | |
| 43 // The unary negation, increment, and decrement operators are supported, along | |
| 44 // with the following unary arithmetic methods, which return a new | |
| 45 // CheckedNumeric as a result of the operation: | |
| 46 // Abs() - Absolute value. | |
| 47 // UnsignedAbs() - Absolute value as an equal-width unsigned underlying type | |
| 48 // (valid for only integral types). | |
| 49 // Max() - Returns whichever is greater of the current instance or argument. | |
| 50 // The underlying return type is whichever has the greatest magnitude. | |
| 51 // Min() - Returns whichever is lowest of the current instance or argument. | |
| 52 // The underlying return type is whichever has can represent the lowest | |
| 53 // number in the smallest width (e.g. int8_t over unsigned, int over | |
| 54 // int8_t, and float over int). | |
| 55 // | |
| 56 // The following methods convert from CheckedNumeric to standard numeric values: | |
| 57 // AssignIfValid() - Assigns the underlying value to the supplied destination | |
| 58 // pointer if the value is currently valid and within the range | |
| 59 // supported by the destination type. Returns true on success. | |
| 60 // **************************************************************************** | |
| 61 // * WARNING: All of the following functions return a StrictNumeric, which * | |
| 62 // * is valid for comparison and assignment operations, but will trigger a * | |
| 63 // * compile failure on attempts to assign to a type of insufficient range. * | |
| 64 // **************************************************************************** | |
| 65 // IsValid() - Returns true if the underlying numeric value is valid (i.e. has | |
| 66 // has not wrapped and is not the result of an invalid conversion). | |
| 67 // ValueOrDie() - Returns the underlying value. If the state is not valid this | |
| 68 // call will crash on a CHECK. | |
| 69 // ValueOrDefault() - Returns the current value, or the supplied default if the | |
| 70 // state is not valid (will not trigger a CHECK). | |
| 71 // | |
| 72 // The following wrapper functions can be used to avoid the template | |
| 73 // disambiguator syntax when converting a destination type. | |
| 74 // IsValidForType<>() in place of: a.template IsValid<Dst>() | |
| 75 // ValueOrDieForType<>() in place of: a.template ValueOrDie() | |
| 76 // ValueOrDefaultForType<>() in place of: a.template ValueOrDefault(default) | |
| 77 // | |
| 78 // The following are general utility methods that are useful for converting | |
| 79 // between arithmetic types and CheckedNumeric types: | |
| 80 // CheckedNumeric::Cast<Dst>() - Instance method returning a CheckedNumeric | |
| 81 // derived from casting the current instance to a CheckedNumeric of | |
| 82 // the supplied destination type. | |
| 83 // MakeCheckedNum() - Creates a new CheckedNumeric from the underlying type of | |
| 84 // the supplied arithmetic, CheckedNumeric, or StrictNumeric type. | |
| 85 // | |
| 86 // Comparison operations are explicitly not supported because they could result | |
| 87 // in a crash on an unexpected CHECK condition. You should use patterns like the | |
| 88 // following for comparisons: | |
| 89 // CheckedNumeric<size_t> checked_size = untrusted_input_value; | |
| 90 // checked_size += HEADER LENGTH; | |
| 91 // if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) | |
| 92 // Do stuff... | |
| 93 | |
| 94 template <typename T> | 18 template <typename T> |
| 95 class CheckedNumeric { | 19 class CheckedNumeric { |
| 96 static_assert(std::is_arithmetic<T>::value, | 20 static_assert(std::is_arithmetic<T>::value, |
| 97 "CheckedNumeric<T>: T must be a numeric type."); | 21 "CheckedNumeric<T>: T must be a numeric type."); |
| 98 | 22 |
| 99 public: | 23 public: |
| 100 using type = T; | 24 using type = T; |
| 101 | 25 |
| 102 constexpr CheckedNumeric() {} | 26 constexpr CheckedNumeric() {} |
| 103 | 27 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 template <typename T> | 294 template <typename T> |
| 371 constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum( | 295 constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum( |
| 372 const T value) { | 296 const T value) { |
| 373 return value; | 297 return value; |
| 374 } | 298 } |
| 375 | 299 |
| 376 // These implement the variadic wrapper for the math operations. | 300 // These implement the variadic wrapper for the math operations. |
| 377 template <template <typename, typename, typename> class M, | 301 template <template <typename, typename, typename> class M, |
| 378 typename L, | 302 typename L, |
| 379 typename R> | 303 typename R> |
| 380 CheckedNumeric<typename MathWrapper<M, L, R>::type> ChkMathOp(const L lhs, | 304 CheckedNumeric<typename MathWrapper<M, L, R>::type> CheckMathOp(const L lhs, |
| 381 const R rhs) { | 305 const R rhs) { |
| 382 using Math = typename MathWrapper<M, L, R>::math; | 306 using Math = typename MathWrapper<M, L, R>::math; |
| 383 return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs, | 307 return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs, |
| 384 rhs); | 308 rhs); |
| 385 } | 309 } |
| 386 | 310 |
| 387 // General purpose wrapper template for arithmetic operations. | 311 // General purpose wrapper template for arithmetic operations. |
| 388 template <template <typename, typename, typename> class M, | 312 template <template <typename, typename, typename> class M, |
| 389 typename L, | 313 typename L, |
| 390 typename R, | 314 typename R, |
| 391 typename... Args> | 315 typename... Args> |
| 392 CheckedNumeric<typename ResultType<M, L, R, Args...>::type> | 316 CheckedNumeric<typename ResultType<M, L, R, Args...>::type> |
| 393 ChkMathOp(const L lhs, const R rhs, const Args... args) { | 317 CheckMathOp(const L lhs, const R rhs, const Args... args) { |
| 394 auto tmp = ChkMathOp<M>(lhs, rhs); | 318 auto tmp = CheckMathOp<M>(lhs, rhs); |
| 395 return tmp.IsValid() ? ChkMathOp<M>(tmp, args...) | 319 return tmp.IsValid() ? CheckMathOp<M>(tmp, args...) |
| 396 : decltype(ChkMathOp<M>(tmp, args...))(tmp); | 320 : decltype(CheckMathOp<M>(tmp, args...))(tmp); |
| 397 } | 321 } |
| 398 | 322 |
| 399 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Add, +, +=) | 323 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Add, +, +=) |
| 400 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Sub, -, -=) | 324 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Sub, -, -=) |
| 401 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mul, *, *=) | 325 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mul, *, *=) |
| 402 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Div, /, /=) | 326 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Div, /, /=) |
| 403 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mod, %, %=) | 327 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mod, %, %=) |
| 404 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Lsh, <<, <<=) | 328 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Lsh, <<, <<=) |
| 405 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Rsh, >>, >>=) | 329 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Rsh, >>, >>=) |
| 406 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, And, &, &=) | 330 BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, And, &, &=) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 using internal::CheckMod; | 368 using internal::CheckMod; |
| 445 using internal::CheckLsh; | 369 using internal::CheckLsh; |
| 446 using internal::CheckRsh; | 370 using internal::CheckRsh; |
| 447 using internal::CheckAnd; | 371 using internal::CheckAnd; |
| 448 using internal::CheckOr; | 372 using internal::CheckOr; |
| 449 using internal::CheckXor; | 373 using internal::CheckXor; |
| 450 | 374 |
| 451 } // namespace base | 375 } // namespace base |
| 452 | 376 |
| 453 #endif // BASE_NUMERICS_CHECKED_MATH_H_ | 377 #endif // BASE_NUMERICS_CHECKED_MATH_H_ |
| OLD | NEW |