from_pointer_cast_test.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // Copyright 2017 The Crashpad Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "util/misc/from_pointer_cast.h"
  15. #include <stdlib.h>
  16. #include <sys/types.h>
  17. #include <limits>
  18. #include "build/build_config.h"
  19. #include "gtest/gtest.h"
  20. #include "test/gtest_death_check.h"
  21. namespace crashpad {
  22. namespace test {
  23. namespace {
  24. struct SomeType {};
  25. template <typename T>
  26. class FromPointerCastTest : public testing::Test {};
  27. using FromPointerCastTestTypes = testing::Types<void*,
  28. const void*,
  29. volatile void*,
  30. const volatile void*,
  31. SomeType*,
  32. const SomeType*,
  33. volatile SomeType*,
  34. const volatile SomeType*>;
  35. TYPED_TEST_CASE(FromPointerCastTest, FromPointerCastTestTypes);
  36. TYPED_TEST(FromPointerCastTest, ToSigned) {
  37. EXPECT_EQ(FromPointerCast<int64_t>(nullptr), 0);
  38. EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(1)), 1);
  39. EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(-1)), -1);
  40. EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(
  41. std::numeric_limits<uintptr_t>::max())),
  42. static_cast<intptr_t>(std::numeric_limits<uintptr_t>::max()));
  43. EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(
  44. std::numeric_limits<intptr_t>::min())),
  45. std::numeric_limits<intptr_t>::min());
  46. EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(
  47. std::numeric_limits<intptr_t>::max())),
  48. std::numeric_limits<intptr_t>::max());
  49. }
  50. TYPED_TEST(FromPointerCastTest, ToUnsigned) {
  51. EXPECT_EQ(FromPointerCast<uint64_t>(nullptr), 0u);
  52. EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(1)), 1u);
  53. EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(-1)),
  54. static_cast<uintptr_t>(-1));
  55. EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(
  56. std::numeric_limits<uintptr_t>::max())),
  57. std::numeric_limits<uintptr_t>::max());
  58. EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(
  59. std::numeric_limits<intptr_t>::min())),
  60. static_cast<uintptr_t>(std::numeric_limits<intptr_t>::min()));
  61. EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(
  62. std::numeric_limits<intptr_t>::max())),
  63. static_cast<uintptr_t>(std::numeric_limits<intptr_t>::max()));
  64. }
  65. // MatchCV<YourType, CVQualifiedType>::Type adapts YourType to match the
  66. // const/void qualification of CVQualifiedType.
  67. template <typename Base, typename MatchTo>
  68. struct MatchCV {
  69. private:
  70. using NonCVBase = typename std::remove_cv<Base>::type;
  71. public:
  72. using Type = typename std::conditional<
  73. std::is_const<MatchTo>::value,
  74. typename std::conditional<std::is_volatile<MatchTo>::value,
  75. const volatile NonCVBase,
  76. const NonCVBase>::type,
  77. typename std::conditional<std::is_volatile<MatchTo>::value,
  78. volatile NonCVBase,
  79. NonCVBase>::type>::type;
  80. };
  81. #if defined(COMPILER_MSVC) && _MSC_VER < 1910
  82. // gtest under MSVS 2015 (MSC 19.0) doesn’t handle EXPECT_EQ(a, b) when a or b
  83. // is a pointer to a volatile type, because it can’t figure out how to print
  84. // them.
  85. template <typename T>
  86. typename std::remove_volatile<typename std::remove_pointer<T>::type>::type*
  87. MaybeRemoveVolatile(const T& value) {
  88. return const_cast<typename std::remove_volatile<
  89. typename std::remove_pointer<T>::type>::type*>(value);
  90. }
  91. #else // COMPILER_MSVC && _MSC_VER < 1910
  92. // This isn’t a problem in MSVS 2017 (MSC 19.1) or with other compilers.
  93. template <typename T>
  94. T MaybeRemoveVolatile(const T& value) {
  95. return value;
  96. }
  97. #endif // COMPILER_MSVC && _MSC_VER < 1910
  98. TYPED_TEST(FromPointerCastTest, ToPointer) {
  99. using CVSomeType =
  100. typename MatchCV<SomeType,
  101. typename std::remove_pointer<TypeParam>::type>::Type;
  102. EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(nullptr)),
  103. MaybeRemoveVolatile(static_cast<CVSomeType*>(nullptr)));
  104. EXPECT_EQ(MaybeRemoveVolatile(
  105. FromPointerCast<CVSomeType*>(reinterpret_cast<TypeParam>(1))),
  106. MaybeRemoveVolatile(reinterpret_cast<CVSomeType*>(1)));
  107. EXPECT_EQ(MaybeRemoveVolatile(
  108. FromPointerCast<CVSomeType*>(reinterpret_cast<TypeParam>(-1))),
  109. MaybeRemoveVolatile(reinterpret_cast<CVSomeType*>(-1)));
  110. EXPECT_EQ(
  111. MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(
  112. reinterpret_cast<TypeParam>(std::numeric_limits<uintptr_t>::max()))),
  113. MaybeRemoveVolatile(reinterpret_cast<CVSomeType*>(
  114. std::numeric_limits<uintptr_t>::max())));
  115. EXPECT_EQ(
  116. MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(
  117. reinterpret_cast<TypeParam>(std::numeric_limits<intptr_t>::min()))),
  118. MaybeRemoveVolatile(
  119. reinterpret_cast<CVSomeType*>(std::numeric_limits<intptr_t>::min())));
  120. EXPECT_EQ(
  121. MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(
  122. reinterpret_cast<TypeParam>(std::numeric_limits<intptr_t>::max()))),
  123. MaybeRemoveVolatile(
  124. reinterpret_cast<CVSomeType*>(std::numeric_limits<intptr_t>::max())));
  125. }
  126. TEST(FromPointerCast, FromFunctionPointer) {
  127. // These casts should work with or without the & in &malloc.
  128. EXPECT_NE(FromPointerCast<int64_t>(malloc), 0);
  129. EXPECT_NE(FromPointerCast<int64_t>(&malloc), 0);
  130. EXPECT_NE(FromPointerCast<uint64_t>(malloc), 0u);
  131. EXPECT_NE(FromPointerCast<uint64_t>(&malloc), 0u);
  132. EXPECT_EQ(FromPointerCast<void*>(malloc), reinterpret_cast<void*>(malloc));
  133. EXPECT_EQ(FromPointerCast<void*>(&malloc), reinterpret_cast<void*>(malloc));
  134. EXPECT_EQ(FromPointerCast<const void*>(malloc),
  135. reinterpret_cast<const void*>(malloc));
  136. EXPECT_EQ(FromPointerCast<const void*>(&malloc),
  137. reinterpret_cast<const void*>(malloc));
  138. EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile void*>(malloc)),
  139. MaybeRemoveVolatile(reinterpret_cast<volatile void*>(malloc)));
  140. EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile void*>(&malloc)),
  141. MaybeRemoveVolatile(reinterpret_cast<volatile void*>(malloc)));
  142. EXPECT_EQ(
  143. MaybeRemoveVolatile(FromPointerCast<const volatile void*>(malloc)),
  144. MaybeRemoveVolatile(reinterpret_cast<const volatile void*>(malloc)));
  145. EXPECT_EQ(
  146. MaybeRemoveVolatile(FromPointerCast<const volatile void*>(&malloc)),
  147. MaybeRemoveVolatile(reinterpret_cast<const volatile void*>(malloc)));
  148. EXPECT_EQ(FromPointerCast<SomeType*>(malloc),
  149. reinterpret_cast<SomeType*>(malloc));
  150. EXPECT_EQ(FromPointerCast<SomeType*>(&malloc),
  151. reinterpret_cast<SomeType*>(malloc));
  152. EXPECT_EQ(FromPointerCast<const SomeType*>(malloc),
  153. reinterpret_cast<const SomeType*>(malloc));
  154. EXPECT_EQ(FromPointerCast<const SomeType*>(&malloc),
  155. reinterpret_cast<const SomeType*>(malloc));
  156. EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile SomeType*>(malloc)),
  157. MaybeRemoveVolatile(reinterpret_cast<volatile SomeType*>(malloc)));
  158. EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile SomeType*>(&malloc)),
  159. MaybeRemoveVolatile(reinterpret_cast<volatile SomeType*>(malloc)));
  160. EXPECT_EQ(
  161. MaybeRemoveVolatile(FromPointerCast<const volatile SomeType*>(malloc)),
  162. MaybeRemoveVolatile(reinterpret_cast<const volatile SomeType*>(malloc)));
  163. EXPECT_EQ(
  164. MaybeRemoveVolatile(FromPointerCast<const volatile SomeType*>(&malloc)),
  165. MaybeRemoveVolatile(reinterpret_cast<const volatile SomeType*>(malloc)));
  166. }
  167. TEST(FromPointerCast, ToNarrowInteger) {
  168. EXPECT_EQ(FromPointerCast<int>(nullptr), 0);
  169. EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(1)), 1);
  170. EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(-1)), -1);
  171. EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(
  172. static_cast<intptr_t>(std::numeric_limits<int>::max()))),
  173. std::numeric_limits<int>::max());
  174. EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(
  175. static_cast<intptr_t>(std::numeric_limits<int>::min()))),
  176. std::numeric_limits<int>::min());
  177. EXPECT_EQ(FromPointerCast<unsigned int>(nullptr), 0u);
  178. EXPECT_EQ(FromPointerCast<unsigned int>(reinterpret_cast<void*>(1)), 1u);
  179. EXPECT_EQ(
  180. FromPointerCast<unsigned int>(reinterpret_cast<void*>(
  181. static_cast<uintptr_t>(std::numeric_limits<unsigned int>::max()))),
  182. std::numeric_limits<unsigned int>::max());
  183. EXPECT_EQ(FromPointerCast<unsigned int>(reinterpret_cast<void*>(
  184. static_cast<uintptr_t>(std::numeric_limits<int>::max()))),
  185. static_cast<unsigned int>(std::numeric_limits<int>::max()));
  186. // int and unsigned int may not be narrower than a pointer, so also test short
  187. // and unsigned short.
  188. EXPECT_EQ(FromPointerCast<short>(nullptr), 0);
  189. EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(1)), 1);
  190. EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(-1)), -1);
  191. EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(
  192. static_cast<intptr_t>(std::numeric_limits<short>::max()))),
  193. std::numeric_limits<short>::max());
  194. EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(
  195. static_cast<intptr_t>(std::numeric_limits<short>::min()))),
  196. std::numeric_limits<short>::min());
  197. EXPECT_EQ(FromPointerCast<unsigned short>(nullptr), 0u);
  198. EXPECT_EQ(FromPointerCast<unsigned short>(reinterpret_cast<void*>(1)), 1u);
  199. EXPECT_EQ(
  200. FromPointerCast<unsigned short>(reinterpret_cast<void*>(
  201. static_cast<uintptr_t>(std::numeric_limits<unsigned short>::max()))),
  202. std::numeric_limits<unsigned short>::max());
  203. EXPECT_EQ(FromPointerCast<unsigned short>(reinterpret_cast<void*>(
  204. static_cast<uintptr_t>(std::numeric_limits<short>::max()))),
  205. static_cast<unsigned short>(std::numeric_limits<short>::max()));
  206. }
  207. TEST(FromPointerCastDeathTest, ToNarrowInteger) {
  208. if (sizeof(int) < sizeof(void*)) {
  209. EXPECT_DEATH(FromPointerCast<int>(
  210. reinterpret_cast<void*>(static_cast<uintptr_t>(
  211. std::numeric_limits<unsigned int>::max() + 1ull))),
  212. "");
  213. EXPECT_DEATH(FromPointerCast<unsigned int>(
  214. reinterpret_cast<void*>(static_cast<uintptr_t>(
  215. std::numeric_limits<unsigned int>::max() + 1ull))),
  216. "");
  217. }
  218. // int and unsigned int may not be narrower than a pointer, so also test short
  219. // and unsigned short.
  220. EXPECT_DEATH(FromPointerCast<short>(
  221. reinterpret_cast<void*>(static_cast<uintptr_t>(
  222. std::numeric_limits<unsigned short>::max() + 1u))),
  223. "");
  224. EXPECT_DEATH(FromPointerCast<unsigned short>(
  225. reinterpret_cast<void*>(static_cast<uintptr_t>(
  226. std::numeric_limits<unsigned short>::max() + 1u))),
  227. "");
  228. }
  229. } // namespace
  230. } // namespace test
  231. } // namespace crashpad