| OLD | NEW |
| 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 PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ | 5 #ifndef PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ |
| 6 #define PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ | 6 #define PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ |
| 7 | 7 |
| 8 #include <stddef.h> |
| 8 #include <stdint.h> | 9 #include <stdint.h> |
| 9 | 10 |
| 11 #include <climits> |
| 10 #include <cmath> | 12 #include <cmath> |
| 11 #include <cstdlib> | 13 #include <cstdlib> |
| 12 #include <limits> | 14 #include <limits> |
| 13 #include <type_traits> | 15 #include <type_traits> |
| 14 | 16 |
| 15 #include "safe_conversions.h" | 17 #include "safe_conversions.h" |
| 16 #include "third_party/base/macros.h" | 18 #include "third_party/base/macros.h" |
| 17 | 19 |
| 18 namespace pdfium { | 20 namespace pdfium { |
| 19 namespace base { | 21 namespace base { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 std::numeric_limits<Integer>::is_integer, | 85 std::numeric_limits<Integer>::is_integer, |
| 84 typename IntegerForSizeAndSign< | 86 typename IntegerForSizeAndSign< |
| 85 sizeof(Integer) * 2, | 87 sizeof(Integer) * 2, |
| 86 std::numeric_limits<Integer>::is_signed>::type>::type type; | 88 std::numeric_limits<Integer>::is_signed>::type>::type type; |
| 87 }; | 89 }; |
| 88 | 90 |
| 89 template <typename Integer> | 91 template <typename Integer> |
| 90 struct PositionOfSignBit { | 92 struct PositionOfSignBit { |
| 91 static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, | 93 static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, |
| 92 size_t>::type value = | 94 size_t>::type value = |
| 93 8 * sizeof(Integer) - 1; | 95 CHAR_BIT * sizeof(Integer) - 1; |
| 94 }; | 96 }; |
| 95 | 97 |
| 96 // Helper templates for integer manipulations. | 98 // Helper templates for integer manipulations. |
| 97 | 99 |
| 98 template <typename T> | 100 template <typename T> |
| 99 bool HasSignBit(T x) { | 101 constexpr bool HasSignBit(T x) { |
| 100 // Cast to unsigned since right shift on signed is undefined. | 102 // Cast to unsigned since right shift on signed is undefined. |
| 101 return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >> | 103 return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >> |
| 102 PositionOfSignBit<T>::value); | 104 PositionOfSignBit<T>::value); |
| 103 } | 105 } |
| 104 | 106 |
| 105 // This wrapper undoes the standard integer promotions. | 107 // This wrapper undoes the standard integer promotions. |
| 106 template <typename T> | 108 template <typename T> |
| 107 T BinaryComplement(T x) { | 109 constexpr T BinaryComplement(T x) { |
| 108 return ~x; | 110 return static_cast<T>(~x); |
| 109 } | 111 } |
| 110 | 112 |
| 111 // Here are the actual portable checked integer math implementations. | 113 // Here are the actual portable checked integer math implementations. |
| 112 // TODO(jschuh): Break this code out from the enable_if pattern and find a clean | 114 // TODO(jschuh): Break this code out from the enable_if pattern and find a clean |
| 113 // way to coalesce things into the CheckedNumericState specializations below. | 115 // way to coalesce things into the CheckedNumericState specializations below. |
| 114 | 116 |
| 115 template <typename T> | 117 template <typename T> |
| 116 typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type | 118 typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type |
| 117 CheckedAdd(T x, T y, RangeConstraint* validity) { | 119 CheckedAdd(T x, T y, RangeConstraint* validity) { |
| 118 // Since the value of x+y is undefined if we have a signed type, we compute | 120 // Since the value of x+y is undefined if we have a signed type, we compute |
| 119 // it using the unsigned type of the same size. | 121 // it using the unsigned type of the same size. |
| 120 typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; | 122 typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; |
| 121 UnsignedDst ux = static_cast<UnsignedDst>(x); | 123 UnsignedDst ux = static_cast<UnsignedDst>(x); |
| 122 UnsignedDst uy = static_cast<UnsignedDst>(y); | 124 UnsignedDst uy = static_cast<UnsignedDst>(y); |
| 123 UnsignedDst uresult = ux + uy; | 125 UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy); |
| 124 // Addition is valid if the sign of (x + y) is equal to either that of x or | 126 // Addition is valid if the sign of (x + y) is equal to either that of x or |
| 125 // that of y. | 127 // that of y. |
| 126 if (std::numeric_limits<T>::is_signed) { | 128 if (std::numeric_limits<T>::is_signed) { |
| 127 if (HasSignBit(BinaryComplement((uresult ^ ux) & (uresult ^ uy)))) | 129 if (HasSignBit(BinaryComplement( |
| 130 static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy))))) { |
| 128 *validity = RANGE_VALID; | 131 *validity = RANGE_VALID; |
| 129 else // Direction of wrap is inverse of result sign. | 132 } else { // Direction of wrap is inverse of result sign. |
| 130 *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; | 133 *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; |
| 131 | 134 } |
| 132 } else { // Unsigned is either valid or overflow. | 135 } else { // Unsigned is either valid or overflow. |
| 133 *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW; | 136 *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW; |
| 134 } | 137 } |
| 135 return static_cast<T>(uresult); | 138 return static_cast<T>(uresult); |
| 136 } | 139 } |
| 137 | 140 |
| 138 template <typename T> | 141 template <typename T> |
| 139 typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type | 142 typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type |
| 140 CheckedSub(T x, T y, RangeConstraint* validity) { | 143 CheckedSub(T x, T y, RangeConstraint* validity) { |
| 141 // Since the value of x+y is undefined if we have a signed type, we compute | 144 // Since the value of x+y is undefined if we have a signed type, we compute |
| 142 // it using the unsigned type of the same size. | 145 // it using the unsigned type of the same size. |
| 143 typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; | 146 typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; |
| 144 UnsignedDst ux = static_cast<UnsignedDst>(x); | 147 UnsignedDst ux = static_cast<UnsignedDst>(x); |
| 145 UnsignedDst uy = static_cast<UnsignedDst>(y); | 148 UnsignedDst uy = static_cast<UnsignedDst>(y); |
| 146 UnsignedDst uresult = ux - uy; | 149 UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy); |
| 147 // Subtraction is valid if either x and y have same sign, or (x-y) and x have | 150 // Subtraction is valid if either x and y have same sign, or (x-y) and x have |
| 148 // the same sign. | 151 // the same sign. |
| 149 if (std::numeric_limits<T>::is_signed) { | 152 if (std::numeric_limits<T>::is_signed) { |
| 150 if (HasSignBit(BinaryComplement((uresult ^ ux) & (ux ^ uy)))) | 153 if (HasSignBit(BinaryComplement( |
| 154 static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy))))) { |
| 151 *validity = RANGE_VALID; | 155 *validity = RANGE_VALID; |
| 152 else // Direction of wrap is inverse of result sign. | 156 } else { // Direction of wrap is inverse of result sign. |
| 153 *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; | 157 *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; |
| 154 | 158 } |
| 155 } else { // Unsigned is either valid or underflow. | 159 } else { // Unsigned is either valid or underflow. |
| 156 *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW; | 160 *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW; |
| 157 } | 161 } |
| 158 return static_cast<T>(uresult); | 162 return static_cast<T>(uresult); |
| 159 } | 163 } |
| 160 | 164 |
| 161 // Integer multiplication is a bit complicated. In the fast case we just | 165 // Integer multiplication is a bit complicated. In the fast case we just |
| 162 // we just promote to a twice wider type, and range check the result. In the | 166 // we just promote to a twice wider type, and range check the result. In the |
| 163 // slow case we need to manually check that the result won't be truncated by | 167 // slow case we need to manually check that the result won't be truncated by |
| 164 // checking with division against the appropriate bound. | 168 // checking with division against the appropriate bound. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 175 } | 179 } |
| 176 | 180 |
| 177 template <typename T> | 181 template <typename T> |
| 178 typename std::enable_if<std::numeric_limits<T>::is_integer && | 182 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 179 std::numeric_limits<T>::is_signed && | 183 std::numeric_limits<T>::is_signed && |
| 180 (sizeof(T) * 2 > sizeof(uintmax_t)), | 184 (sizeof(T) * 2 > sizeof(uintmax_t)), |
| 181 T>::type | 185 T>::type |
| 182 CheckedMul(T x, T y, RangeConstraint* validity) { | 186 CheckedMul(T x, T y, RangeConstraint* validity) { |
| 183 // If either side is zero then the result will be zero. | 187 // If either side is zero then the result will be zero. |
| 184 if (!x || !y) { | 188 if (!x || !y) { |
| 185 return RANGE_VALID; | 189 *validity = RANGE_VALID; |
| 186 | 190 return static_cast<T>(0); |
| 187 } else if (x > 0) { | 191 } |
| 188 if (y > 0) | 192 if (x > 0) { |
| 193 if (y > 0) { |
| 189 *validity = | 194 *validity = |
| 190 x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW; | 195 x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW; |
| 191 else | 196 } else { |
| 192 *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID | 197 *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID |
| 193 : RANGE_UNDERFLOW; | 198 : RANGE_UNDERFLOW; |
| 194 | 199 } |
| 195 } else { | 200 } else { |
| 196 if (y > 0) | 201 if (y > 0) { |
| 197 *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID | 202 *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID |
| 198 : RANGE_UNDERFLOW; | 203 : RANGE_UNDERFLOW; |
| 199 else | 204 } else { |
| 200 *validity = | 205 *validity = |
| 201 y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; | 206 y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; |
| 207 } |
| 202 } | 208 } |
| 203 | 209 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0); |
| 204 return x * y; | |
| 205 } | 210 } |
| 206 | 211 |
| 207 template <typename T> | 212 template <typename T> |
| 208 typename std::enable_if<std::numeric_limits<T>::is_integer && | 213 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 209 !std::numeric_limits<T>::is_signed && | 214 !std::numeric_limits<T>::is_signed && |
| 210 (sizeof(T) * 2 > sizeof(uintmax_t)), | 215 (sizeof(T) * 2 > sizeof(uintmax_t)), |
| 211 T>::type | 216 T>::type |
| 212 CheckedMul(T x, T y, RangeConstraint* validity) { | 217 CheckedMul(T x, T y, RangeConstraint* validity) { |
| 213 *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) | 218 *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) |
| 214 ? RANGE_VALID | 219 ? RANGE_VALID |
| 215 : RANGE_OVERFLOW; | 220 : RANGE_OVERFLOW; |
| 216 return x * y; | 221 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0); |
| 217 } | 222 } |
| 218 | 223 |
| 219 // Division just requires a check for an invalid negation on signed min/-1. | 224 // Division just requires a check for a zero denominator or an invalid negation |
| 225 // on signed min/-1. |
| 220 template <typename T> | 226 template <typename T> |
| 221 T CheckedDiv(T x, | 227 T CheckedDiv(T x, |
| 222 T y, | 228 T y, |
| 223 RangeConstraint* validity, | 229 RangeConstraint* validity, |
| 224 typename std::enable_if<std::numeric_limits<T>::is_integer, | 230 typename std::enable_if<std::numeric_limits<T>::is_integer, |
| 225 int>::type = 0) { | 231 int>::type = 0) { |
| 232 if (y == 0) { |
| 233 *validity = RANGE_INVALID; |
| 234 return static_cast<T>(0); |
| 235 } |
| 226 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && | 236 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && |
| 227 y == static_cast<T>(-1)) { | 237 y == static_cast<T>(-1)) { |
| 228 *validity = RANGE_OVERFLOW; | 238 *validity = RANGE_OVERFLOW; |
| 229 return std::numeric_limits<T>::min(); | 239 return std::numeric_limits<T>::min(); |
| 230 } | 240 } |
| 231 | |
| 232 *validity = RANGE_VALID; | 241 *validity = RANGE_VALID; |
| 233 return x / y; | 242 return static_cast<T>(x / y); |
| 234 } | 243 } |
| 235 | 244 |
| 236 template <typename T> | 245 template <typename T> |
| 237 typename std::enable_if<std::numeric_limits<T>::is_integer && | 246 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 238 std::numeric_limits<T>::is_signed, | 247 std::numeric_limits<T>::is_signed, |
| 239 T>::type | 248 T>::type |
| 240 CheckedMod(T x, T y, RangeConstraint* validity) { | 249 CheckedMod(T x, T y, RangeConstraint* validity) { |
| 241 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; | 250 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; |
| 242 return x % y; | 251 return static_cast<T>(*validity == RANGE_VALID ? x % y : 0); |
| 243 } | 252 } |
| 244 | 253 |
| 245 template <typename T> | 254 template <typename T> |
| 246 typename std::enable_if<std::numeric_limits<T>::is_integer && | 255 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 247 !std::numeric_limits<T>::is_signed, | 256 !std::numeric_limits<T>::is_signed, |
| 248 T>::type | 257 T>::type |
| 249 CheckedMod(T x, T y, RangeConstraint* validity) { | 258 CheckedMod(T x, T y, RangeConstraint* validity) { |
| 250 *validity = RANGE_VALID; | 259 *validity = y != 0 ? RANGE_VALID : RANGE_INVALID; |
| 251 return x % y; | 260 return static_cast<T>(*validity == RANGE_VALID ? x % y : 0); |
| 252 } | 261 } |
| 253 | 262 |
| 254 template <typename T> | 263 template <typename T> |
| 255 typename std::enable_if<std::numeric_limits<T>::is_integer && | 264 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 256 std::numeric_limits<T>::is_signed, | 265 std::numeric_limits<T>::is_signed, |
| 257 T>::type | 266 T>::type |
| 258 CheckedNeg(T value, RangeConstraint* validity) { | 267 CheckedNeg(T value, RangeConstraint* validity) { |
| 259 *validity = | 268 *validity = |
| 260 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; | 269 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; |
| 261 // The negation of signed min is min, so catch that one. | 270 // The negation of signed min is min, so catch that one. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 return value; | 302 return value; |
| 294 } | 303 } |
| 295 | 304 |
| 296 // These are the floating point stubs that the compiler needs to see. Only the | 305 // These are the floating point stubs that the compiler needs to see. Only the |
| 297 // negation operation is ever called. | 306 // negation operation is ever called. |
| 298 #define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ | 307 #define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ |
| 299 template <typename T> \ | 308 template <typename T> \ |
| 300 typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type \ | 309 typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type \ |
| 301 Checked##NAME(T, T, RangeConstraint*) { \ | 310 Checked##NAME(T, T, RangeConstraint*) { \ |
| 302 NOTREACHED(); \ | 311 NOTREACHED(); \ |
| 303 return 0; \ | 312 return static_cast<T>(0); \ |
| 304 } | 313 } |
| 305 | 314 |
| 306 BASE_FLOAT_ARITHMETIC_STUBS(Add) | 315 BASE_FLOAT_ARITHMETIC_STUBS(Add) |
| 307 BASE_FLOAT_ARITHMETIC_STUBS(Sub) | 316 BASE_FLOAT_ARITHMETIC_STUBS(Sub) |
| 308 BASE_FLOAT_ARITHMETIC_STUBS(Mul) | 317 BASE_FLOAT_ARITHMETIC_STUBS(Mul) |
| 309 BASE_FLOAT_ARITHMETIC_STUBS(Div) | 318 BASE_FLOAT_ARITHMETIC_STUBS(Div) |
| 310 BASE_FLOAT_ARITHMETIC_STUBS(Mod) | 319 BASE_FLOAT_ARITHMETIC_STUBS(Mod) |
| 311 | 320 |
| 312 #undef BASE_FLOAT_ARITHMETIC_STUBS | 321 #undef BASE_FLOAT_ARITHMETIC_STUBS |
| 313 | 322 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 StaticDstRangeRelationToSrcRange<T, Rhs>::value != | 507 StaticDstRangeRelationToSrcRange<T, Rhs>::value != |
| 499 NUMERIC_RANGE_CONTAINED && | 508 NUMERIC_RANGE_CONTAINED && |
| 500 sizeof(T) >= (2 * sizeof(Rhs)); | 509 sizeof(T) >= (2 * sizeof(Rhs)); |
| 501 }; | 510 }; |
| 502 | 511 |
| 503 } // namespace internal | 512 } // namespace internal |
| 504 } // namespace base | 513 } // namespace base |
| 505 } // namespace pdfium | 514 } // namespace pdfium |
| 506 | 515 |
| 507 #endif // PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ | 516 #endif // PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ |
| OLD | NEW |