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 |