From 66bd67023f747c489d7144aaf4ca6222c686cd26 Mon Sep 17 00:00:00 2001 From: tsepez Date: Wed, 2 Nov 2016 13:26:50 -0700 Subject: Take more current safe_math_impl.h from upstream. Corresponds to version dfd77a987650965071d0fddfbe0b806ce62ba337. Major change is to handle div by 0 without exceptions. Safe shift is not yet present. TBR=thestig@chromium.org TBR=jschuh@chromium.org Review-Url: https://codereview.chromium.org/2473513002 --- third_party/base/numerics/safe_math_impl.h | 96 +++++++++++++++++++----------- 1 file changed, 61 insertions(+), 35 deletions(-) (limited to 'third_party') diff --git a/third_party/base/numerics/safe_math_impl.h b/third_party/base/numerics/safe_math_impl.h index 959b7f1b61..f950f5d517 100644 --- a/third_party/base/numerics/safe_math_impl.h +++ b/third_party/base/numerics/safe_math_impl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ -#define PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ +#ifndef PDFIUM_THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_IMPL_H_ +#define PDFIUM_THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_IMPL_H_ #include #include @@ -14,8 +14,8 @@ #include #include -#include "safe_conversions.h" #include "third_party/base/macros.h" +#include "third_party/base/numerics/safe_conversions.h" namespace pdfium { namespace base { @@ -95,6 +95,25 @@ struct PositionOfSignBit { CHAR_BIT * sizeof(Integer) - 1; }; +// This is used for UnsignedAbs, where we need to support floating-point +// template instantiations even though we don't actually support the operations. +// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs, +// so the float versions will not compile. +template ::is_integer, + bool IsFloat = std::numeric_limits::is_iec559> +struct UnsignedOrFloatForSize; + +template +struct UnsignedOrFloatForSize { + typedef typename UnsignedIntegerForSize::type type; +}; + +template +struct UnsignedOrFloatForSize { + typedef Numeric type; +}; + // Helper templates for integer manipulations. template @@ -238,6 +257,7 @@ T CheckedDiv(T x, *validity = RANGE_OVERFLOW; return std::numeric_limits::min(); } + *validity = RANGE_VALID; return static_cast(x / y); } @@ -268,7 +288,7 @@ CheckedNeg(T value, RangeConstraint* validity) { *validity = value != std::numeric_limits::min() ? RANGE_VALID : RANGE_OVERFLOW; // The negation of signed min is min, so catch that one. - return -value; + return static_cast(*validity == RANGE_VALID ? -value : 0); } template @@ -279,7 +299,9 @@ CheckedNeg(T value, RangeConstraint* validity) { // The only legal unsigned negation is zero. *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; return static_cast( - -static_cast::type>(value)); + *validity == RANGE_VALID + ? -static_cast::type>(value) + : 0); } template @@ -289,7 +311,7 @@ typename std::enable_if::is_integer && CheckedAbs(T value, RangeConstraint* validity) { *validity = value != std::numeric_limits::min() ? RANGE_VALID : RANGE_OVERFLOW; - return std::abs(value); + return static_cast(*validity == RANGE_VALID ? std::abs(value) : 0); } template @@ -297,11 +319,31 @@ typename std::enable_if::is_integer && !std::numeric_limits::is_signed, T>::type CheckedAbs(T value, RangeConstraint* validity) { - // Absolute value of a positive is just its identiy. + // T is unsigned, so |value| must already be positive. *validity = RANGE_VALID; return value; } +template +typename std::enable_if::is_integer && + std::numeric_limits::is_signed, + typename UnsignedIntegerForSize::type>::type +CheckedUnsignedAbs(T value) { + typedef typename UnsignedIntegerForSize::type UnsignedT; + return value == std::numeric_limits::min() + ? static_cast(std::numeric_limits::max()) + 1 + : static_cast(std::abs(value)); +} + +template +typename std::enable_if::is_integer && + !std::numeric_limits::is_signed, + T>::type +CheckedUnsignedAbs(T value) { + // T is unsigned, so |value| must already be positive. + return static_cast(value); +} + // These are the floating point stubs that the compiler needs to see. Only the // negation operation is ever called. #define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ @@ -324,14 +366,14 @@ template typename std::enable_if::is_iec559, T>::type CheckedNeg( T value, RangeConstraint*) { - return -value; + return static_cast(-value); } template typename std::enable_if::is_iec559, T>::type CheckedAbs( T value, RangeConstraint*) { - return std::abs(value); + return static_cast(std::abs(value)); } // Floats carry around their validity state with them, but integers do not. So, @@ -361,7 +403,7 @@ template class CheckedNumericState { private: T value_; - RangeConstraint validity_; + RangeConstraint validity_ : CHAR_BIT; // Actually requires only two bits. public: template @@ -371,11 +413,11 @@ class CheckedNumericState { template CheckedNumericState(Src value, RangeConstraint validity) - : value_(value), + : value_(static_cast(value)), validity_(GetRangeConstraint(validity | DstRangeRelationToSrcRange(value))) { - COMPILE_ASSERT(std::numeric_limits::is_specialized, - argument_must_be_numeric); + static_assert(std::numeric_limits::is_specialized, + "Argument must be numeric."); } // Copy constructor. @@ -456,27 +498,16 @@ class CheckedNumericState { T value() const { return value_; } }; -// For integers less than 128-bit and floats 32-bit or larger, we can distil -// C/C++ arithmetic promotions down to two simple rules: -// 1. The type with the larger maximum exponent always takes precedence. -// 2. The resulting type must be promoted to at least an int. -// The following template specializations implement that promotion logic. -enum ArithmeticPromotionCategory { - LEFT_PROMOTION, - RIGHT_PROMOTION, - DEFAULT_PROMOTION -}; +// For integers less than 128-bit and floats 32-bit or larger, we have the type +// with the larger maximum exponent take precedence. +enum ArithmeticPromotionCategory { LEFT_PROMOTION, RIGHT_PROMOTION }; template ::value > MaxExponent::value) - ? (MaxExponent::value > MaxExponent::value - ? LEFT_PROMOTION - : DEFAULT_PROMOTION) - : (MaxExponent::value > MaxExponent::value - ? RIGHT_PROMOTION - : DEFAULT_PROMOTION) > + ? LEFT_PROMOTION + : RIGHT_PROMOTION> struct ArithmeticPromotion; template @@ -489,11 +520,6 @@ struct ArithmeticPromotion { typedef Rhs type; }; -template -struct ArithmeticPromotion { - typedef int type; -}; - // We can statically check if operations on the provided types can wrap, so we // can skip the checked operations if they're not needed. So, for an integer we // care if the destination type preserves the sign and is twice the width of @@ -513,4 +539,4 @@ struct IsIntegerArithmeticSafe { } // namespace base } // namespace pdfium -#endif // PDFIUM_THIRD_PARTY_SAFE_MATH_IMPL_H_ +#endif // PDFIUM_THIRD_PARTY_BASE_NUMERICS_SAFE_MATH_IMPL_H_ -- cgit v1.2.3