123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- // Copyright 2017 The Crashpad Authors. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "util/misc/from_pointer_cast.h"
- #include <stdlib.h>
- #include <sys/types.h>
- #include <limits>
- #include "build/build_config.h"
- #include "gtest/gtest.h"
- #include "test/gtest_death_check.h"
- namespace crashpad {
- namespace test {
- namespace {
- struct SomeType {};
- template <typename T>
- class FromPointerCastTest : public testing::Test {};
- using FromPointerCastTestTypes = testing::Types<void*,
- const void*,
- volatile void*,
- const volatile void*,
- SomeType*,
- const SomeType*,
- volatile SomeType*,
- const volatile SomeType*>;
- TYPED_TEST_CASE(FromPointerCastTest, FromPointerCastTestTypes);
- TYPED_TEST(FromPointerCastTest, ToSigned) {
- EXPECT_EQ(FromPointerCast<int64_t>(nullptr), 0);
- EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(1)), 1);
- EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(-1)), -1);
- EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(
- std::numeric_limits<uintptr_t>::max())),
- static_cast<intptr_t>(std::numeric_limits<uintptr_t>::max()));
- EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(
- std::numeric_limits<intptr_t>::min())),
- std::numeric_limits<intptr_t>::min());
- EXPECT_EQ(FromPointerCast<int64_t>(reinterpret_cast<TypeParam>(
- std::numeric_limits<intptr_t>::max())),
- std::numeric_limits<intptr_t>::max());
- }
- TYPED_TEST(FromPointerCastTest, ToUnsigned) {
- EXPECT_EQ(FromPointerCast<uint64_t>(nullptr), 0u);
- EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(1)), 1u);
- EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(-1)),
- static_cast<uintptr_t>(-1));
- EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(
- std::numeric_limits<uintptr_t>::max())),
- std::numeric_limits<uintptr_t>::max());
- EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(
- std::numeric_limits<intptr_t>::min())),
- static_cast<uintptr_t>(std::numeric_limits<intptr_t>::min()));
- EXPECT_EQ(FromPointerCast<uint64_t>(reinterpret_cast<TypeParam>(
- std::numeric_limits<intptr_t>::max())),
- static_cast<uintptr_t>(std::numeric_limits<intptr_t>::max()));
- }
- // MatchCV<YourType, CVQualifiedType>::Type adapts YourType to match the
- // const/void qualification of CVQualifiedType.
- template <typename Base, typename MatchTo>
- struct MatchCV {
- private:
- using NonCVBase = typename std::remove_cv<Base>::type;
- public:
- using Type = typename std::conditional<
- std::is_const<MatchTo>::value,
- typename std::conditional<std::is_volatile<MatchTo>::value,
- const volatile NonCVBase,
- const NonCVBase>::type,
- typename std::conditional<std::is_volatile<MatchTo>::value,
- volatile NonCVBase,
- NonCVBase>::type>::type;
- };
- #if defined(COMPILER_MSVC) && _MSC_VER < 1910
- // gtest under MSVS 2015 (MSC 19.0) doesn’t handle EXPECT_EQ(a, b) when a or b
- // is a pointer to a volatile type, because it can’t figure out how to print
- // them.
- template <typename T>
- typename std::remove_volatile<typename std::remove_pointer<T>::type>::type*
- MaybeRemoveVolatile(const T& value) {
- return const_cast<typename std::remove_volatile<
- typename std::remove_pointer<T>::type>::type*>(value);
- }
- #else // COMPILER_MSVC && _MSC_VER < 1910
- // This isn’t a problem in MSVS 2017 (MSC 19.1) or with other compilers.
- template <typename T>
- T MaybeRemoveVolatile(const T& value) {
- return value;
- }
- #endif // COMPILER_MSVC && _MSC_VER < 1910
- TYPED_TEST(FromPointerCastTest, ToPointer) {
- using CVSomeType =
- typename MatchCV<SomeType,
- typename std::remove_pointer<TypeParam>::type>::Type;
- EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(nullptr)),
- MaybeRemoveVolatile(static_cast<CVSomeType*>(nullptr)));
- EXPECT_EQ(MaybeRemoveVolatile(
- FromPointerCast<CVSomeType*>(reinterpret_cast<TypeParam>(1))),
- MaybeRemoveVolatile(reinterpret_cast<CVSomeType*>(1)));
- EXPECT_EQ(MaybeRemoveVolatile(
- FromPointerCast<CVSomeType*>(reinterpret_cast<TypeParam>(-1))),
- MaybeRemoveVolatile(reinterpret_cast<CVSomeType*>(-1)));
- EXPECT_EQ(
- MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(
- reinterpret_cast<TypeParam>(std::numeric_limits<uintptr_t>::max()))),
- MaybeRemoveVolatile(reinterpret_cast<CVSomeType*>(
- std::numeric_limits<uintptr_t>::max())));
- EXPECT_EQ(
- MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(
- reinterpret_cast<TypeParam>(std::numeric_limits<intptr_t>::min()))),
- MaybeRemoveVolatile(
- reinterpret_cast<CVSomeType*>(std::numeric_limits<intptr_t>::min())));
- EXPECT_EQ(
- MaybeRemoveVolatile(FromPointerCast<CVSomeType*>(
- reinterpret_cast<TypeParam>(std::numeric_limits<intptr_t>::max()))),
- MaybeRemoveVolatile(
- reinterpret_cast<CVSomeType*>(std::numeric_limits<intptr_t>::max())));
- }
- TEST(FromPointerCast, FromFunctionPointer) {
- // These casts should work with or without the & in &malloc.
- EXPECT_NE(FromPointerCast<int64_t>(malloc), 0);
- EXPECT_NE(FromPointerCast<int64_t>(&malloc), 0);
- EXPECT_NE(FromPointerCast<uint64_t>(malloc), 0u);
- EXPECT_NE(FromPointerCast<uint64_t>(&malloc), 0u);
- EXPECT_EQ(FromPointerCast<void*>(malloc), reinterpret_cast<void*>(malloc));
- EXPECT_EQ(FromPointerCast<void*>(&malloc), reinterpret_cast<void*>(malloc));
- EXPECT_EQ(FromPointerCast<const void*>(malloc),
- reinterpret_cast<const void*>(malloc));
- EXPECT_EQ(FromPointerCast<const void*>(&malloc),
- reinterpret_cast<const void*>(malloc));
- EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile void*>(malloc)),
- MaybeRemoveVolatile(reinterpret_cast<volatile void*>(malloc)));
- EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile void*>(&malloc)),
- MaybeRemoveVolatile(reinterpret_cast<volatile void*>(malloc)));
- EXPECT_EQ(
- MaybeRemoveVolatile(FromPointerCast<const volatile void*>(malloc)),
- MaybeRemoveVolatile(reinterpret_cast<const volatile void*>(malloc)));
- EXPECT_EQ(
- MaybeRemoveVolatile(FromPointerCast<const volatile void*>(&malloc)),
- MaybeRemoveVolatile(reinterpret_cast<const volatile void*>(malloc)));
- EXPECT_EQ(FromPointerCast<SomeType*>(malloc),
- reinterpret_cast<SomeType*>(malloc));
- EXPECT_EQ(FromPointerCast<SomeType*>(&malloc),
- reinterpret_cast<SomeType*>(malloc));
- EXPECT_EQ(FromPointerCast<const SomeType*>(malloc),
- reinterpret_cast<const SomeType*>(malloc));
- EXPECT_EQ(FromPointerCast<const SomeType*>(&malloc),
- reinterpret_cast<const SomeType*>(malloc));
- EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile SomeType*>(malloc)),
- MaybeRemoveVolatile(reinterpret_cast<volatile SomeType*>(malloc)));
- EXPECT_EQ(MaybeRemoveVolatile(FromPointerCast<volatile SomeType*>(&malloc)),
- MaybeRemoveVolatile(reinterpret_cast<volatile SomeType*>(malloc)));
- EXPECT_EQ(
- MaybeRemoveVolatile(FromPointerCast<const volatile SomeType*>(malloc)),
- MaybeRemoveVolatile(reinterpret_cast<const volatile SomeType*>(malloc)));
- EXPECT_EQ(
- MaybeRemoveVolatile(FromPointerCast<const volatile SomeType*>(&malloc)),
- MaybeRemoveVolatile(reinterpret_cast<const volatile SomeType*>(malloc)));
- }
- TEST(FromPointerCast, ToNarrowInteger) {
- EXPECT_EQ(FromPointerCast<int>(nullptr), 0);
- EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(1)), 1);
- EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(-1)), -1);
- EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(
- static_cast<intptr_t>(std::numeric_limits<int>::max()))),
- std::numeric_limits<int>::max());
- EXPECT_EQ(FromPointerCast<int>(reinterpret_cast<void*>(
- static_cast<intptr_t>(std::numeric_limits<int>::min()))),
- std::numeric_limits<int>::min());
- EXPECT_EQ(FromPointerCast<unsigned int>(nullptr), 0u);
- EXPECT_EQ(FromPointerCast<unsigned int>(reinterpret_cast<void*>(1)), 1u);
- EXPECT_EQ(
- FromPointerCast<unsigned int>(reinterpret_cast<void*>(
- static_cast<uintptr_t>(std::numeric_limits<unsigned int>::max()))),
- std::numeric_limits<unsigned int>::max());
- EXPECT_EQ(FromPointerCast<unsigned int>(reinterpret_cast<void*>(
- static_cast<uintptr_t>(std::numeric_limits<int>::max()))),
- static_cast<unsigned int>(std::numeric_limits<int>::max()));
- // int and unsigned int may not be narrower than a pointer, so also test short
- // and unsigned short.
- EXPECT_EQ(FromPointerCast<short>(nullptr), 0);
- EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(1)), 1);
- EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(-1)), -1);
- EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(
- static_cast<intptr_t>(std::numeric_limits<short>::max()))),
- std::numeric_limits<short>::max());
- EXPECT_EQ(FromPointerCast<short>(reinterpret_cast<void*>(
- static_cast<intptr_t>(std::numeric_limits<short>::min()))),
- std::numeric_limits<short>::min());
- EXPECT_EQ(FromPointerCast<unsigned short>(nullptr), 0u);
- EXPECT_EQ(FromPointerCast<unsigned short>(reinterpret_cast<void*>(1)), 1u);
- EXPECT_EQ(
- FromPointerCast<unsigned short>(reinterpret_cast<void*>(
- static_cast<uintptr_t>(std::numeric_limits<unsigned short>::max()))),
- std::numeric_limits<unsigned short>::max());
- EXPECT_EQ(FromPointerCast<unsigned short>(reinterpret_cast<void*>(
- static_cast<uintptr_t>(std::numeric_limits<short>::max()))),
- static_cast<unsigned short>(std::numeric_limits<short>::max()));
- }
- TEST(FromPointerCastDeathTest, ToNarrowInteger) {
- if (sizeof(int) < sizeof(void*)) {
- EXPECT_DEATH(FromPointerCast<int>(
- reinterpret_cast<void*>(static_cast<uintptr_t>(
- std::numeric_limits<unsigned int>::max() + 1ull))),
- "");
- EXPECT_DEATH(FromPointerCast<unsigned int>(
- reinterpret_cast<void*>(static_cast<uintptr_t>(
- std::numeric_limits<unsigned int>::max() + 1ull))),
- "");
- }
- // int and unsigned int may not be narrower than a pointer, so also test short
- // and unsigned short.
- EXPECT_DEATH(FromPointerCast<short>(
- reinterpret_cast<void*>(static_cast<uintptr_t>(
- std::numeric_limits<unsigned short>::max() + 1u))),
- "");
- EXPECT_DEATH(FromPointerCast<unsigned short>(
- reinterpret_cast<void*>(static_cast<uintptr_t>(
- std::numeric_limits<unsigned short>::max() + 1u))),
- "");
- }
- } // namespace
- } // namespace test
- } // namespace crashpad
|