safemath.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // Copyright (c) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  4. //
  5. // ---------------------------------------------------------------------------
  6. // safemath.h
  7. //
  8. // overflow checking infrastructure
  9. // ---------------------------------------------------------------------------
  10. #ifndef SAFEMATH_H_
  11. #define SAFEMATH_H_
  12. #include <debugmacrosext.h>
  13. #ifndef _ASSERTE_SAFEMATH
  14. #ifdef _ASSERTE
  15. // Use _ASSERTE if we have it (should always be the case in the CLR)
  16. #define _ASSERTE_SAFEMATH _ASSERTE
  17. #else
  18. // Otherwise (eg. we're being used from a tool like SOS) there isn't much
  19. // we can rely on that is both available everywhere and rotor-safe. In
  20. // several other tools we just take the recourse of disabling asserts,
  21. // we'll do the same here.
  22. // Ideally we'd have a collection of common utilities available evererywhere.
  23. #define _ASSERTE_SAFEMATH(a)
  24. #endif
  25. #endif
  26. #if !defined(__IOS__) && !defined(OSX_SDK_TR1) && defined(__APPLE__)
  27. #include <AvailabilityMacros.h>
  28. #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < MAC_OS_X_VERSION_10_9
  29. #define OSX_SDK_TR1
  30. #endif
  31. #endif
  32. #ifdef OSX_SDK_TR1
  33. #include <tr1/type_traits>
  34. #else
  35. #include <type_traits>
  36. #endif
  37. //==================================================================
  38. // Semantics: if val can be represented as the exact same value
  39. // when cast to Dst type, then FitsIn<Dst>(val) will return true;
  40. // otherwise FitsIn returns false.
  41. //
  42. // Dst and Src must both be integral types.
  43. //
  44. // It's important to note that most of the conditionals in this
  45. // function are based on static type information and as such will
  46. // be optimized away. In particular, the case where the signs are
  47. // identical will result in no code branches.
  48. #ifdef _PREFAST_
  49. #pragma warning(push)
  50. #pragma warning(disable:6326) // PREfast warning: Potential comparison of a constant with another constant
  51. #endif // _PREFAST_
  52. template <typename Dst, typename Src>
  53. inline bool FitsIn(Src val)
  54. {
  55. #ifdef _MSC_VER
  56. static_assert_no_msg(!__is_class(Dst));
  57. static_assert_no_msg(!__is_class(Src));
  58. #endif
  59. if (std::is_signed<Src>::value == std::is_signed<Dst>::value)
  60. { // Src and Dst are equally signed
  61. if (sizeof(Src) <= sizeof(Dst))
  62. { // No truncation is possible
  63. return true;
  64. }
  65. else
  66. { // Truncation is possible, requiring runtime check
  67. return val == (Src)((Dst)val);
  68. }
  69. }
  70. else if (std::is_signed<Src>::value)
  71. { // Src is signed, Dst is unsigned
  72. #ifdef __GNUC__
  73. // Workaround for GCC warning: "comparison is always
  74. // false due to limited range of data type."
  75. if (!(val == 0 || val > 0))
  76. #else
  77. if (val < 0)
  78. #endif
  79. { // A negative number cannot be represented by an unsigned type
  80. return false;
  81. }
  82. else
  83. {
  84. if (sizeof(Src) <= sizeof(Dst))
  85. { // No truncation is possible
  86. return true;
  87. }
  88. else
  89. { // Truncation is possible, requiring runtime check
  90. return val == (Src)((Dst)val);
  91. }
  92. }
  93. }
  94. else
  95. { // Src is unsigned, Dst is signed
  96. if (sizeof(Src) < sizeof(Dst))
  97. { // No truncation is possible. Note that Src is strictly
  98. // smaller than Dst.
  99. return true;
  100. }
  101. else
  102. { // Truncation is possible, requiring runtime check
  103. #ifdef __GNUC__
  104. // Workaround for GCC warning: "comparison is always
  105. // true due to limited range of data type." If in fact
  106. // Dst were unsigned we'd never execute this code
  107. // anyway.
  108. return ((Dst)val > 0 || (Dst)val == 0) &&
  109. #else
  110. return ((Dst)val >= 0) &&
  111. #endif
  112. (val == (Src)((Dst)val));
  113. }
  114. }
  115. }
  116. // Requires that Dst is an integral type, and that DstMin and DstMax are the
  117. // minimum and maximum values of that type, respectively. Returns "true" iff
  118. // "val" can be represented in the range [DstMin..DstMax] (allowing loss of precision, but
  119. // not truncation).
  120. template <INT64 DstMin, UINT64 DstMax>
  121. inline bool FloatFitsInIntType(float val)
  122. {
  123. float DstMinF = static_cast<float>(DstMin);
  124. float DstMaxF = static_cast<float>(DstMax);
  125. return DstMinF <= val && val <= DstMaxF;
  126. }
  127. template <INT64 DstMin, UINT64 DstMax>
  128. inline bool DoubleFitsInIntType(double val)
  129. {
  130. double DstMinD = static_cast<double>(DstMin);
  131. double DstMaxD = static_cast<double>(DstMax);
  132. return DstMinD <= val && val <= DstMaxD;
  133. }
  134. #ifdef _PREFAST_
  135. #pragma warning(pop)
  136. #endif //_PREFAST_
  137. #define ovadd_lt(a, b, rhs) (((a) + (b) < (rhs) ) && ((a) + (b) >= (a)))
  138. #define ovadd_le(a, b, rhs) (((a) + (b) <= (rhs) ) && ((a) + (b) >= (a)))
  139. #define ovadd_gt(a, b, rhs) (((a) + (b) > (rhs) ) || ((a) + (b) < (a)))
  140. #define ovadd_ge(a, b, rhs) (((a) + (b) >= (rhs) ) || ((a) + (b) < (a)))
  141. #define ovadd3_gt(a, b, c, rhs) (((a) + (b) + (c) > (rhs)) || ((a) + (b) < (a)) || ((a) + (b) + (c) < (c)))
  142. #if defined(_TARGET_X86_) && defined( _MSC_VER )
  143. #define S_SIZE_T_WP64BUG(v) S_SIZE_T( static_cast<UINT32>( v ) )
  144. #else
  145. #define S_SIZE_T_WP64BUG(v) S_SIZE_T( v )
  146. #endif
  147. #endif // SAFEMATH_H_