forked from mirrors/gecko-dev
		
	 0e041b91bd
			
		
	
	
		0e041b91bd
		
	
	
	
	
		
			
			This commit does: - Sync files under security/sandbox/chromium/ with Chromium 81.0.4044.138 - Update files under security/sandbox/chromium-shim/ - Apply patches under security/sandbox/chromium-shim/patches/with_update/ - Add mozilla::AddWin32kLockdownPolicy to apply MITIGATION_WIN32K_DISABLE before SUBSYS_WIN32K_LOCKDOWN Differential Revision: https://phabricator.services.mozilla.com/D79560
		
			
				
	
	
		
			240 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2017 The Chromium Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| #ifndef BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
 | |
| #define BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
 | |
| 
 | |
| #include <stddef.h>
 | |
| #include <stdint.h>
 | |
| 
 | |
| #include <cassert>
 | |
| #include <climits>
 | |
| #include <cmath>
 | |
| #include <cstdlib>
 | |
| #include <limits>
 | |
| #include <type_traits>
 | |
| 
 | |
| #include "base/numerics/safe_conversions.h"
 | |
| 
 | |
| #ifdef __asmjs__
 | |
| // Optimized safe math instructions are incompatible with asmjs.
 | |
| #define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
 | |
| // Where available use builtin math overflow support on Clang and GCC.
 | |
| #elif !defined(__native_client__) &&                         \
 | |
|       ((defined(__clang__) &&                                \
 | |
|         ((__clang_major__ > 3) ||                            \
 | |
|          (__clang_major__ == 3 && __clang_minor__ >= 4))) || \
 | |
|        (defined(__GNUC__) && __GNUC__ >= 5))
 | |
| #include "base/numerics/safe_math_clang_gcc_impl.h"
 | |
| #define BASE_HAS_OPTIMIZED_SAFE_MATH (1)
 | |
| #else
 | |
| #define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
 | |
| #endif
 | |
| 
 | |
| namespace base {
 | |
| namespace internal {
 | |
| 
 | |
| // These are the non-functioning boilerplate implementations of the optimized
 | |
| // safe math routines.
 | |
| #if !BASE_HAS_OPTIMIZED_SAFE_MATH
 | |
| template <typename T, typename U>
 | |
| struct CheckedAddFastOp {
 | |
|   static const bool is_supported = false;
 | |
|   template <typename V>
 | |
|   static constexpr bool Do(T, U, V*) {
 | |
|     // Force a compile failure if instantiated.
 | |
|     return CheckOnFailure::template HandleFailure<bool>();
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T, typename U>
 | |
| struct CheckedSubFastOp {
 | |
|   static const bool is_supported = false;
 | |
|   template <typename V>
 | |
|   static constexpr bool Do(T, U, V*) {
 | |
|     // Force a compile failure if instantiated.
 | |
|     return CheckOnFailure::template HandleFailure<bool>();
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T, typename U>
 | |
| struct CheckedMulFastOp {
 | |
|   static const bool is_supported = false;
 | |
|   template <typename V>
 | |
|   static constexpr bool Do(T, U, V*) {
 | |
|     // Force a compile failure if instantiated.
 | |
|     return CheckOnFailure::template HandleFailure<bool>();
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T, typename U>
 | |
| struct ClampedAddFastOp {
 | |
|   static const bool is_supported = false;
 | |
|   template <typename V>
 | |
|   static constexpr V Do(T, U) {
 | |
|     // Force a compile failure if instantiated.
 | |
|     return CheckOnFailure::template HandleFailure<V>();
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T, typename U>
 | |
| struct ClampedSubFastOp {
 | |
|   static const bool is_supported = false;
 | |
|   template <typename V>
 | |
|   static constexpr V Do(T, U) {
 | |
|     // Force a compile failure if instantiated.
 | |
|     return CheckOnFailure::template HandleFailure<V>();
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T, typename U>
 | |
| struct ClampedMulFastOp {
 | |
|   static const bool is_supported = false;
 | |
|   template <typename V>
 | |
|   static constexpr V Do(T, U) {
 | |
|     // Force a compile failure if instantiated.
 | |
|     return CheckOnFailure::template HandleFailure<V>();
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T>
 | |
| struct ClampedNegFastOp {
 | |
|   static const bool is_supported = false;
 | |
|   static constexpr T Do(T) {
 | |
|     // Force a compile failure if instantiated.
 | |
|     return CheckOnFailure::template HandleFailure<T>();
 | |
|   }
 | |
| };
 | |
| #endif  // BASE_HAS_OPTIMIZED_SAFE_MATH
 | |
| #undef BASE_HAS_OPTIMIZED_SAFE_MATH
 | |
| 
 | |
| // 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. SafeUnsignedAbs,
 | |
| // so the float versions will not compile.
 | |
| template <typename Numeric,
 | |
|           bool IsInteger = std::is_integral<Numeric>::value,
 | |
|           bool IsFloat = std::is_floating_point<Numeric>::value>
 | |
| struct UnsignedOrFloatForSize;
 | |
| 
 | |
| template <typename Numeric>
 | |
| struct UnsignedOrFloatForSize<Numeric, true, false> {
 | |
|   using type = typename std::make_unsigned<Numeric>::type;
 | |
| };
 | |
| 
 | |
| template <typename Numeric>
 | |
| struct UnsignedOrFloatForSize<Numeric, false, true> {
 | |
|   using type = Numeric;
 | |
| };
 | |
| 
 | |
| // Wrap the unary operations to allow SFINAE when instantiating integrals versus
 | |
| // floating points. These don't perform any overflow checking. Rather, they
 | |
| // exhibit well-defined overflow semantics and rely on the caller to detect
 | |
| // if an overflow occured.
 | |
| 
 | |
| template <typename T,
 | |
|           typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
 | |
| constexpr T NegateWrapper(T value) {
 | |
|   using UnsignedT = typename std::make_unsigned<T>::type;
 | |
|   // This will compile to a NEG on Intel, and is normal negation on ARM.
 | |
|   return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value));
 | |
| }
 | |
| 
 | |
| template <
 | |
|     typename T,
 | |
|     typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
 | |
| constexpr T NegateWrapper(T value) {
 | |
|   return -value;
 | |
| }
 | |
| 
 | |
| template <typename T,
 | |
|           typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
 | |
| constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) {
 | |
|   return ~value;
 | |
| }
 | |
| 
 | |
| template <typename T,
 | |
|           typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
 | |
| constexpr T AbsWrapper(T value) {
 | |
|   return static_cast<T>(SafeUnsignedAbs(value));
 | |
| }
 | |
| 
 | |
| template <
 | |
|     typename T,
 | |
|     typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
 | |
| constexpr T AbsWrapper(T value) {
 | |
|   return value < 0 ? -value : value;
 | |
| }
 | |
| 
 | |
| template <template <typename, typename, typename> class M,
 | |
|           typename L,
 | |
|           typename R>
 | |
| struct MathWrapper {
 | |
|   using math = M<typename UnderlyingType<L>::type,
 | |
|                  typename UnderlyingType<R>::type,
 | |
|                  void>;
 | |
|   using type = typename math::result_type;
 | |
| };
 | |
| 
 | |
| // These variadic templates work out the return types.
 | |
| // TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support.
 | |
| template <template <typename, typename, typename> class M,
 | |
|           typename L,
 | |
|           typename R,
 | |
|           typename... Args>
 | |
| struct ResultType;
 | |
| 
 | |
| template <template <typename, typename, typename> class M,
 | |
|           typename L,
 | |
|           typename R>
 | |
| struct ResultType<M, L, R> {
 | |
|   using type = typename MathWrapper<M, L, R>::type;
 | |
| };
 | |
| 
 | |
| template <template <typename, typename, typename> class M,
 | |
|           typename L,
 | |
|           typename R,
 | |
|           typename... Args>
 | |
| struct ResultType {
 | |
|   using type =
 | |
|       typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type;
 | |
| };
 | |
| 
 | |
| // The following macros are just boilerplate for the standard arithmetic
 | |
| // operator overloads and variadic function templates. A macro isn't the nicest
 | |
| // solution, but it beats rewriting these over and over again.
 | |
| #define BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)       \
 | |
|   template <typename L, typename R, typename... Args>                   \
 | |
|   constexpr CLASS##Numeric<                                             \
 | |
|       typename ResultType<CLASS##OP_NAME##Op, L, R, Args...>::type>     \
 | |
|       CL_ABBR##OP_NAME(const L lhs, const R rhs, const Args... args) {  \
 | |
|     return CL_ABBR##MathOp<CLASS##OP_NAME##Op, L, R, Args...>(lhs, rhs, \
 | |
|                                                               args...); \
 | |
|   }
 | |
| 
 | |
| #define BASE_NUMERIC_ARITHMETIC_OPERATORS(CLASS, CL_ABBR, OP_NAME, OP, CMP_OP) \
 | |
|   /* Binary arithmetic operator for all CLASS##Numeric operations. */          \
 | |
|   template <typename L, typename R,                                            \
 | |
|             typename std::enable_if<Is##CLASS##Op<L, R>::value>::type* =       \
 | |
|                 nullptr>                                                       \
 | |
|   constexpr CLASS##Numeric<                                                    \
 | |
|       typename MathWrapper<CLASS##OP_NAME##Op, L, R>::type>                    \
 | |
|   operator OP(const L lhs, const R rhs) {                                      \
 | |
|     return decltype(lhs OP rhs)::template MathOp<CLASS##OP_NAME##Op>(lhs,      \
 | |
|                                                                      rhs);     \
 | |
|   }                                                                            \
 | |
|   /* Assignment arithmetic operator implementation from CLASS##Numeric. */     \
 | |
|   template <typename L>                                                        \
 | |
|   template <typename R>                                                        \
 | |
|   constexpr CLASS##Numeric<L>& CLASS##Numeric<L>::operator CMP_OP(             \
 | |
|       const R rhs) {                                                           \
 | |
|     return MathOp<CLASS##OP_NAME##Op>(rhs);                                    \
 | |
|   }                                                                            \
 | |
|   /* Variadic arithmetic functions that return CLASS##Numeric. */              \
 | |
|   BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)
 | |
| 
 | |
| }  // namespace internal
 | |
| }  // namespace base
 | |
| 
 | |
| #endif  // BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
 |