| Index: third_party/base/numerics/safe_math_impl.h
|
| diff --git a/third_party/base/numerics/safe_math_impl.h b/third_party/base/numerics/safe_math_impl.h
|
| index f219cf52bb34cd21cd44f2744937308f8378516a..959b7f1b61a831bb9198d936550c72b467c0062c 100644
|
| --- a/third_party/base/numerics/safe_math_impl.h
|
| +++ b/third_party/base/numerics/safe_math_impl.h
|
| @@ -5,8 +5,10 @@
|
| #ifndef PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_
|
| #define PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_
|
|
|
| +#include <stddef.h>
|
| #include <stdint.h>
|
|
|
| +#include <climits>
|
| #include <cmath>
|
| #include <cstdlib>
|
| #include <limits>
|
| @@ -90,13 +92,13 @@ template <typename Integer>
|
| struct PositionOfSignBit {
|
| static const typename std::enable_if<std::numeric_limits<Integer>::is_integer,
|
| size_t>::type value =
|
| - 8 * sizeof(Integer) - 1;
|
| + CHAR_BIT * sizeof(Integer) - 1;
|
| };
|
|
|
| // Helper templates for integer manipulations.
|
|
|
| template <typename T>
|
| -bool HasSignBit(T x) {
|
| +constexpr bool HasSignBit(T x) {
|
| // Cast to unsigned since right shift on signed is undefined.
|
| return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >>
|
| PositionOfSignBit<T>::value);
|
| @@ -104,8 +106,8 @@ bool HasSignBit(T x) {
|
|
|
| // This wrapper undoes the standard integer promotions.
|
| template <typename T>
|
| -T BinaryComplement(T x) {
|
| - return ~x;
|
| +constexpr T BinaryComplement(T x) {
|
| + return static_cast<T>(~x);
|
| }
|
|
|
| // Here are the actual portable checked integer math implementations.
|
| @@ -120,15 +122,16 @@ CheckedAdd(T x, T y, RangeConstraint* validity) {
|
| typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
|
| UnsignedDst ux = static_cast<UnsignedDst>(x);
|
| UnsignedDst uy = static_cast<UnsignedDst>(y);
|
| - UnsignedDst uresult = ux + uy;
|
| + UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
|
| // Addition is valid if the sign of (x + y) is equal to either that of x or
|
| // that of y.
|
| if (std::numeric_limits<T>::is_signed) {
|
| - if (HasSignBit(BinaryComplement((uresult ^ ux) & (uresult ^ uy))))
|
| + if (HasSignBit(BinaryComplement(
|
| + static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy))))) {
|
| *validity = RANGE_VALID;
|
| - else // Direction of wrap is inverse of result sign.
|
| + } else { // Direction of wrap is inverse of result sign.
|
| *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
|
| -
|
| + }
|
| } else { // Unsigned is either valid or overflow.
|
| *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW;
|
| }
|
| @@ -143,15 +146,16 @@ CheckedSub(T x, T y, RangeConstraint* validity) {
|
| typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
|
| UnsignedDst ux = static_cast<UnsignedDst>(x);
|
| UnsignedDst uy = static_cast<UnsignedDst>(y);
|
| - UnsignedDst uresult = ux - uy;
|
| + UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
|
| // Subtraction is valid if either x and y have same sign, or (x-y) and x have
|
| // the same sign.
|
| if (std::numeric_limits<T>::is_signed) {
|
| - if (HasSignBit(BinaryComplement((uresult ^ ux) & (ux ^ uy))))
|
| + if (HasSignBit(BinaryComplement(
|
| + static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy))))) {
|
| *validity = RANGE_VALID;
|
| - else // Direction of wrap is inverse of result sign.
|
| + } else { // Direction of wrap is inverse of result sign.
|
| *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
|
| -
|
| + }
|
| } else { // Unsigned is either valid or underflow.
|
| *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW;
|
| }
|
| @@ -182,26 +186,27 @@ typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
| CheckedMul(T x, T y, RangeConstraint* validity) {
|
| // If either side is zero then the result will be zero.
|
| if (!x || !y) {
|
| - return RANGE_VALID;
|
| -
|
| - } else if (x > 0) {
|
| - if (y > 0)
|
| + *validity = RANGE_VALID;
|
| + return static_cast<T>(0);
|
| + }
|
| + if (x > 0) {
|
| + if (y > 0) {
|
| *validity =
|
| x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW;
|
| - else
|
| + } else {
|
| *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID
|
| : RANGE_UNDERFLOW;
|
| -
|
| + }
|
| } else {
|
| - if (y > 0)
|
| + if (y > 0) {
|
| *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID
|
| : RANGE_UNDERFLOW;
|
| - else
|
| + } else {
|
| *validity =
|
| y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW;
|
| + }
|
| }
|
| -
|
| - return x * y;
|
| + return static_cast<T>(*validity == RANGE_VALID ? x * y : 0);
|
| }
|
|
|
| template <typename T>
|
| @@ -213,24 +218,28 @@ CheckedMul(T x, T y, RangeConstraint* validity) {
|
| *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y)
|
| ? RANGE_VALID
|
| : RANGE_OVERFLOW;
|
| - return x * y;
|
| + return static_cast<T>(*validity == RANGE_VALID ? x * y : 0);
|
| }
|
|
|
| -// Division just requires a check for an invalid negation on signed min/-1.
|
| +// Division just requires a check for a zero denominator or an invalid negation
|
| +// on signed min/-1.
|
| template <typename T>
|
| T CheckedDiv(T x,
|
| T y,
|
| RangeConstraint* validity,
|
| typename std::enable_if<std::numeric_limits<T>::is_integer,
|
| int>::type = 0) {
|
| + if (y == 0) {
|
| + *validity = RANGE_INVALID;
|
| + return static_cast<T>(0);
|
| + }
|
| if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() &&
|
| y == static_cast<T>(-1)) {
|
| *validity = RANGE_OVERFLOW;
|
| return std::numeric_limits<T>::min();
|
| }
|
| -
|
| *validity = RANGE_VALID;
|
| - return x / y;
|
| + return static_cast<T>(x / y);
|
| }
|
|
|
| template <typename T>
|
| @@ -239,7 +248,7 @@ typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
| T>::type
|
| CheckedMod(T x, T y, RangeConstraint* validity) {
|
| *validity = y > 0 ? RANGE_VALID : RANGE_INVALID;
|
| - return x % y;
|
| + return static_cast<T>(*validity == RANGE_VALID ? x % y : 0);
|
| }
|
|
|
| template <typename T>
|
| @@ -247,8 +256,8 @@ typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
| !std::numeric_limits<T>::is_signed,
|
| T>::type
|
| CheckedMod(T x, T y, RangeConstraint* validity) {
|
| - *validity = RANGE_VALID;
|
| - return x % y;
|
| + *validity = y != 0 ? RANGE_VALID : RANGE_INVALID;
|
| + return static_cast<T>(*validity == RANGE_VALID ? x % y : 0);
|
| }
|
|
|
| template <typename T>
|
| @@ -300,7 +309,7 @@ CheckedAbs(T value, RangeConstraint* validity) {
|
| typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type \
|
| Checked##NAME(T, T, RangeConstraint*) { \
|
| NOTREACHED(); \
|
| - return 0; \
|
| + return static_cast<T>(0); \
|
| }
|
|
|
| BASE_FLOAT_ARITHMETIC_STUBS(Add)
|
|
|