Use FromPointerCast<>() in many places where it makes sense

I opted to leave casts to types that were definitely the same size
alone. reinterpret_cast<uintptr_t>(pointer) and
reinterpret_cast<intptr_t>(pointer) should always be safe, for example.
Casts to other integral types have been replaced with
FromPointerCast<>(), which does zero-extension or sign-extension based
on the target type.

To make it possible to use FromPointerCast<>() with some use sites that
were already using checked_cast<>(), FromPointerCast<>() now uses
check_cast<>() when converting to a narrower type.

Test: crashpad_util_test FromPointerCast*, others
Change-Id: I4a71b4aa2d87f545c75524290a702f5f3138d675
Reviewed-on: https://chromium-review.googlesource.com/489701
Reviewed-by: Scott Graham <scottmg@chromium.org>
This commit is contained in:
Mark Mentovai 2017-04-28 10:08:35 -04:00
parent 984749479f
commit 15103742e0
19 changed files with 173 additions and 88 deletions

View File

@ -30,6 +30,7 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "util/file/file_io.h" #include "util/file/file_io.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/random_string.h" #include "util/misc/random_string.h"
#include "util/win/address_types.h" #include "util/win/address_types.h"
#include "util/win/capture_context.h" #include "util/win/capture_context.h"
@ -156,7 +157,7 @@ LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
// signal the crash handler. // signal the crash handler.
g_crash_exception_information.thread_id = GetCurrentThreadId(); g_crash_exception_information.thread_id = GetCurrentThreadId();
g_crash_exception_information.exception_pointers = g_crash_exception_information.exception_pointers =
reinterpret_cast<WinVMAddress>(exception_pointers); FromPointerCast<WinVMAddress>(exception_pointers);
// Now signal the crash server, which will take a dump and then terminate us // Now signal the crash server, which will take a dump and then terminate us
// when it's complete. // when it's complete.
@ -390,9 +391,9 @@ bool StartHandlerProcess(
g_non_crash_dump_done, g_non_crash_dump_done,
data->ipc_pipe_handle.get(), data->ipc_pipe_handle.get(),
this_process.get(), this_process.get(),
reinterpret_cast<WinVMAddress>(&g_crash_exception_information), FromPointerCast<WinVMAddress>(&g_crash_exception_information),
reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information), FromPointerCast<WinVMAddress>(&g_non_crash_exception_information),
reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info)); FromPointerCast<WinVMAddress>(&g_critical_section_with_debug_info));
AppendCommandLineArgument( AppendCommandLineArgument(
base::UTF8ToUTF16(std::string("--initial-client-data=") + base::UTF8ToUTF16(std::string("--initial-client-data=") +
initial_client_data.StringRepresentation()), initial_client_data.StringRepresentation()),
@ -655,14 +656,14 @@ bool CrashpadClient::SetHandlerIPCPipe(const std::wstring& ipc_pipe) {
message.registration.version = RegistrationRequest::kMessageVersion; message.registration.version = RegistrationRequest::kMessageVersion;
message.registration.client_process_id = GetCurrentProcessId(); message.registration.client_process_id = GetCurrentProcessId();
message.registration.crash_exception_information = message.registration.crash_exception_information =
reinterpret_cast<WinVMAddress>(&g_crash_exception_information); FromPointerCast<WinVMAddress>(&g_crash_exception_information);
message.registration.non_crash_exception_information = message.registration.non_crash_exception_information =
reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information); FromPointerCast<WinVMAddress>(&g_non_crash_exception_information);
CommonInProcessInitialization(); CommonInProcessInitialization();
message.registration.critical_section_address = message.registration.critical_section_address =
reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info); FromPointerCast<WinVMAddress>(&g_critical_section_with_debug_info);
ServerToClientMessage response = {}; ServerToClientMessage response = {};
@ -765,7 +766,7 @@ void CrashpadClient::DumpWithoutCrash(const CONTEXT& context) {
g_non_crash_exception_information.thread_id = GetCurrentThreadId(); g_non_crash_exception_information.thread_id = GetCurrentThreadId();
g_non_crash_exception_information.exception_pointers = g_non_crash_exception_information.exception_pointers =
reinterpret_cast<WinVMAddress>(&exception_pointers); FromPointerCast<WinVMAddress>(&exception_pointers);
bool set_event_result = !!SetEvent(g_signal_non_crash_dump); bool set_event_result = !!SetEvent(g_signal_non_crash_dump);
PLOG_IF(ERROR, !set_event_result) << "SetEvent"; PLOG_IF(ERROR, !set_event_result) << "SetEvent";
@ -830,7 +831,7 @@ bool CrashpadClient::DumpAndCrashTargetProcess(HANDLE process,
const size_t kInjectBufferSize = 4 * 1024; const size_t kInjectBufferSize = 4 * 1024;
WinVMAddress inject_memory = WinVMAddress inject_memory =
reinterpret_cast<WinVMAddress>(VirtualAllocEx(process, FromPointerCast<WinVMAddress>(VirtualAllocEx(process,
nullptr, nullptr,
kInjectBufferSize, kInjectBufferSize,
MEM_RESERVE | MEM_COMMIT, MEM_RESERVE | MEM_COMMIT,
@ -844,7 +845,7 @@ bool CrashpadClient::DumpAndCrashTargetProcess(HANDLE process,
// loaded at the same address in our process as the target, and just look up // loaded at the same address in our process as the target, and just look up
// its address here. // its address here.
WinVMAddress raise_exception_address = WinVMAddress raise_exception_address =
reinterpret_cast<WinVMAddress>(&RaiseException); FromPointerCast<WinVMAddress>(&RaiseException);
WinVMAddress code_entry_point = 0; WinVMAddress code_entry_point = 0;
std::vector<unsigned char> data_to_write; std::vector<unsigned char> data_to_write;

View File

@ -15,6 +15,7 @@
#include "client/crashpad_info.h" #include "client/crashpad_info.h"
#include "util/misc/address_sanitizer.h" #include "util/misc/address_sanitizer.h"
#include "util/misc/from_pointer_cast.h"
#include "util/stdlib/cxx.h" #include "util/stdlib/cxx.h"
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
@ -131,11 +132,10 @@ void CrashpadInfo::AddUserDataMinidumpStream(uint32_t stream_type,
const void* data, const void* data,
size_t size) { size_t size) {
auto to_be_added = new internal::UserDataMinidumpStreamListEntry(); auto to_be_added = new internal::UserDataMinidumpStreamListEntry();
to_be_added->next = base::checked_cast<uint64_t>( to_be_added->next =
reinterpret_cast<uintptr_t>(user_data_minidump_stream_head_)); FromPointerCast<uint64_t>(user_data_minidump_stream_head_);
to_be_added->stream_type = stream_type; to_be_added->stream_type = stream_type;
to_be_added->base_address = to_be_added->base_address = FromPointerCast<uint64_t>(data);
base::checked_cast<uint64_t>(reinterpret_cast<uintptr_t>(data));
to_be_added->size = base::checked_cast<uint64_t>(size); to_be_added->size = base::checked_cast<uint64_t>(size);
user_data_minidump_stream_head_ = to_be_added; user_data_minidump_stream_head_ = to_be_added;
} }

View File

@ -19,6 +19,8 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "util/misc/from_pointer_cast.h"
#include "util/numeric/checked_range.h" #include "util/numeric/checked_range.h"
namespace crashpad { namespace crashpad {
@ -138,8 +140,7 @@ class TSimpleAddressRangeBag {
bool Insert(void* base, size_t size) { bool Insert(void* base, size_t size) {
DCHECK(base != nullptr); DCHECK(base != nullptr);
DCHECK_NE(0u, size); DCHECK_NE(0u, size);
return Insert(CheckedRange<uint64_t>( return Insert(CheckedRange<uint64_t>(FromPointerCast<uint64_t>(base),
base::checked_cast<uint64_t>(reinterpret_cast<uintptr_t>(base)),
base::checked_cast<uint64_t>(size))); base::checked_cast<uint64_t>(size)));
} }
@ -175,8 +176,7 @@ class TSimpleAddressRangeBag {
bool Remove(void* base, size_t size) { bool Remove(void* base, size_t size) {
DCHECK(base != nullptr); DCHECK(base != nullptr);
DCHECK_NE(0u, size); DCHECK_NE(0u, size);
return Remove(CheckedRange<uint64_t>( return Remove(CheckedRange<uint64_t>(FromPointerCast<uint64_t>(base),
base::checked_cast<uint64_t>(reinterpret_cast<uintptr_t>(base)),
base::checked_cast<uint64_t>(size))); base::checked_cast<uint64_t>(size)));
} }

View File

@ -17,6 +17,7 @@
#include "snapshot/win/pe_image_annotations_reader.h" #include "snapshot/win/pe_image_annotations_reader.h"
#include "snapshot/win/pe_image_reader.h" #include "snapshot/win/pe_image_reader.h"
#include "snapshot/win/process_reader_win.h" #include "snapshot/win/process_reader_win.h"
#include "util/misc/from_pointer_cast.h"
#include "util/win/get_module_information.h" #include "util/win/get_module_information.h"
namespace crashpad { namespace crashpad {
@ -38,7 +39,7 @@ bool ReadModuleAnnotations(HANDLE process,
PEImageReader image_reader; PEImageReader image_reader;
if (!image_reader.Initialize( if (!image_reader.Initialize(
&process_reader, &process_reader,
reinterpret_cast<crashpad::WinVMAddress>(module_info.lpBaseOfDll), FromPointerCast<WinVMAddress>(module_info.lpBaseOfDll),
module_info.SizeOfImage, module_info.SizeOfImage,
"")) ""))
return false; return false;

View File

@ -32,6 +32,7 @@
#include "snapshot/mac/process_reader.h" #include "snapshot/mac/process_reader.h"
#include "snapshot/mac/process_types.h" #include "snapshot/mac/process_types.h"
#include "test/mac/dyld.h" #include "test/mac/dyld.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/implicit_cast.h" #include "util/misc/implicit_cast.h"
#include "util/misc/uuid.h" #include "util/misc/uuid.h"
@ -133,7 +134,7 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
const uint8_t* expect_segment_data = getsegmentdata( const uint8_t* expect_segment_data = getsegmentdata(
expect_image, segment_name.c_str(), &expect_segment_size); expect_image, segment_name.c_str(), &expect_segment_size);
mach_vm_address_t expect_segment_address = mach_vm_address_t expect_segment_address =
reinterpret_cast<mach_vm_address_t>(expect_segment_data); FromPointerCast<mach_vm_address_t>(expect_segment_data);
EXPECT_EQ(actual_segment->Address(), expect_segment_address); EXPECT_EQ(actual_segment->Address(), expect_segment_address);
EXPECT_EQ(actual_segment->vmsize(), expect_segment_size); EXPECT_EQ(actual_segment->vmsize(), expect_segment_size);
EXPECT_EQ(actual_segment->Size(), actual_segment->vmsize()); EXPECT_EQ(actual_segment->Size(), actual_segment->vmsize());
@ -191,7 +192,7 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
section_name.c_str(), section_name.c_str(),
&expect_section_size); &expect_section_size);
mach_vm_address_t expect_section_address = mach_vm_address_t expect_section_address =
reinterpret_cast<mach_vm_address_t>(expect_section_data); FromPointerCast<mach_vm_address_t>(expect_section_data);
EXPECT_EQ(actual_section_address, expect_section_address); EXPECT_EQ(actual_section_address, expect_section_address);
EXPECT_EQ(actual_section->size, expect_section_size); EXPECT_EQ(actual_section->size, expect_section_size);
} else { } else {
@ -501,7 +502,7 @@ TEST(MachOImageReader, Self_MainExecutable) {
reinterpret_cast<MachHeader*>(dlsym(RTLD_MAIN_ONLY, MH_EXECUTE_SYM)); reinterpret_cast<MachHeader*>(dlsym(RTLD_MAIN_ONLY, MH_EXECUTE_SYM));
ASSERT_NE(mh_execute_header, nullptr); ASSERT_NE(mh_execute_header, nullptr);
mach_vm_address_t mh_execute_header_address = mach_vm_address_t mh_execute_header_address =
reinterpret_cast<mach_vm_address_t>(mh_execute_header); FromPointerCast<mach_vm_address_t>(mh_execute_header);
MachOImageReader image_reader; MachOImageReader image_reader;
ASSERT_TRUE(image_reader.Initialize( ASSERT_TRUE(image_reader.Initialize(
@ -547,7 +548,7 @@ TEST(MachOImageReader, Self_DyldImages) {
const MachHeader* mach_header = const MachHeader* mach_header =
reinterpret_cast<const MachHeader*>(_dyld_get_image_header(index)); reinterpret_cast<const MachHeader*>(_dyld_get_image_header(index));
mach_vm_address_t image_address = mach_vm_address_t image_address =
reinterpret_cast<mach_vm_address_t>(mach_header); FromPointerCast<mach_vm_address_t>(mach_header);
MachOImageReader image_reader; MachOImageReader image_reader;
ASSERT_TRUE( ASSERT_TRUE(
@ -588,7 +589,7 @@ TEST(MachOImageReader, Self_DyldImages) {
const MachHeader* mach_header = reinterpret_cast<const MachHeader*>( const MachHeader* mach_header = reinterpret_cast<const MachHeader*>(
dyld_image_infos->dyldImageLoadAddress); dyld_image_infos->dyldImageLoadAddress);
mach_vm_address_t image_address = mach_vm_address_t image_address =
reinterpret_cast<mach_vm_address_t>(mach_header); FromPointerCast<mach_vm_address_t>(mach_header);
MachOImageReader image_reader; MachOImageReader image_reader;
ASSERT_TRUE( ASSERT_TRUE(
@ -619,7 +620,7 @@ TEST(MachOImageReader, Self_DyldImages) {
const MachHeader* mach_header = const MachHeader* mach_header =
reinterpret_cast<const MachHeader*>(dyld_image->imageLoadAddress); reinterpret_cast<const MachHeader*>(dyld_image->imageLoadAddress);
mach_vm_address_t image_address = mach_vm_address_t image_address =
reinterpret_cast<mach_vm_address_t>(mach_header); FromPointerCast<mach_vm_address_t>(mach_header);
MachOImageReader image_reader; MachOImageReader image_reader;
ASSERT_TRUE( ASSERT_TRUE(

View File

@ -40,6 +40,7 @@
#include "util/file/file_io.h" #include "util/file/file_io.h"
#include "util/mac/mac_util.h" #include "util/mac/mac_util.h"
#include "util/mach/mach_extensions.h" #include "util/mach/mach_extensions.h"
#include "util/misc/from_pointer_cast.h"
#include "util/stdlib/pointer_container.h" #include "util/stdlib/pointer_container.h"
#include "util/synchronization/semaphore.h" #include "util/synchronization/semaphore.h"
@ -74,7 +75,7 @@ TEST(ProcessReader, SelfBasic) {
const char kTestMemory[] = "Some test memory"; const char kTestMemory[] = "Some test memory";
char buffer[arraysize(kTestMemory)]; char buffer[arraysize(kTestMemory)];
ASSERT_TRUE(process_reader.Memory()->Read( ASSERT_TRUE(process_reader.Memory()->Read(
reinterpret_cast<mach_vm_address_t>(kTestMemory), FromPointerCast<mach_vm_address_t>(kTestMemory),
sizeof(kTestMemory), sizeof(kTestMemory),
&buffer)); &buffer));
EXPECT_STREQ(kTestMemory, buffer); EXPECT_STREQ(kTestMemory, buffer);
@ -115,8 +116,7 @@ class ProcessReaderChild final : public MachMultiprocess {
void MachMultiprocessChild() override { void MachMultiprocessChild() override {
FileHandle write_handle = WritePipeHandle(); FileHandle write_handle = WritePipeHandle();
mach_vm_address_t address = mach_vm_address_t address = FromPointerCast<mach_vm_address_t>(kTestMemory);
reinterpret_cast<mach_vm_address_t>(kTestMemory);
CheckedWriteFile(write_handle, &address, sizeof(address)); CheckedWriteFile(write_handle, &address, sizeof(address));
// Wait for the parent to signal that its OK to exit by closing its end of // Wait for the parent to signal that its OK to exit by closing its end of
@ -282,7 +282,7 @@ class TestThreadPool {
ThreadInfo* thread_info = static_cast<ThreadInfo*>(argument); ThreadInfo* thread_info = static_cast<ThreadInfo*>(argument);
thread_info->stack_address = thread_info->stack_address =
reinterpret_cast<mach_vm_address_t>(&thread_info); FromPointerCast<mach_vm_address_t>(&thread_info);
thread_info->ready_semaphore.Signal(); thread_info->ready_semaphore.Signal();
thread_info->exit_semaphore.Wait(); thread_info->exit_semaphore.Wait();
@ -391,7 +391,7 @@ TEST(ProcessReader, SelfSeveralThreads) {
ThreadMap thread_map; ThreadMap thread_map;
const uint64_t self_thread_id = PthreadToThreadID(pthread_self()); const uint64_t self_thread_id = PthreadToThreadID(pthread_self());
TestThreadPool::ThreadExpectation expectation; TestThreadPool::ThreadExpectation expectation;
expectation.stack_address = reinterpret_cast<mach_vm_address_t>(&thread_map); expectation.stack_address = FromPointerCast<mach_vm_address_t>(&thread_map);
expectation.suspend_count = 0; expectation.suspend_count = 0;
thread_map[self_thread_id] = expectation; thread_map[self_thread_id] = expectation;
for (size_t thread_index = 0; thread_index < kChildThreads; ++thread_index) { for (size_t thread_index = 0; thread_index < kChildThreads; ++thread_index) {
@ -484,7 +484,7 @@ class ProcessReaderThreadedChild final : public MachMultiprocess {
CheckedWriteFile(write_handle, &thread_id, sizeof(thread_id)); CheckedWriteFile(write_handle, &thread_id, sizeof(thread_id));
TestThreadPool::ThreadExpectation expectation; TestThreadPool::ThreadExpectation expectation;
expectation.stack_address = reinterpret_cast<mach_vm_address_t>(&thread_id); expectation.stack_address = FromPointerCast<mach_vm_address_t>(&thread_id);
expectation.suspend_count = 0; expectation.suspend_count = 0;
CheckedWriteFile(write_handle, CheckedWriteFile(write_handle,
@ -667,7 +667,7 @@ TEST(ProcessReader, SelfModules) {
ASSERT_TRUE(modules[index].reader); ASSERT_TRUE(modules[index].reader);
EXPECT_EQ( EXPECT_EQ(
modules[index].reader->Address(), modules[index].reader->Address(),
reinterpret_cast<mach_vm_address_t>(_dyld_get_image_header(index))); FromPointerCast<mach_vm_address_t>(_dyld_get_image_header(index)));
if (index == 0) { if (index == 0) {
// dyld didnt load the main executable, so it couldnt record its // dyld didnt load the main executable, so it couldnt record its
@ -703,7 +703,7 @@ TEST(ProcessReader, SelfModules) {
if (dyld_image_infos->version >= 2) { if (dyld_image_infos->version >= 2) {
ASSERT_TRUE(modules[index].reader); ASSERT_TRUE(modules[index].reader);
EXPECT_EQ(modules[index].reader->Address(), EXPECT_EQ(modules[index].reader->Address(),
reinterpret_cast<mach_vm_address_t>( FromPointerCast<mach_vm_address_t>(
dyld_image_infos->dyldImageLoadAddress)); dyld_image_infos->dyldImageLoadAddress));
} }
} }
@ -801,10 +801,10 @@ class ProcessReaderModulesChild final : public MachMultiprocess {
if (index < dyld_image_count) { if (index < dyld_image_count) {
dyld_image_name = _dyld_get_image_name(index); dyld_image_name = _dyld_get_image_name(index);
dyld_image_address = dyld_image_address =
reinterpret_cast<mach_vm_address_t>(_dyld_get_image_header(index)); FromPointerCast<mach_vm_address_t>(_dyld_get_image_header(index));
} else { } else {
dyld_image_name = kDyldPath; dyld_image_name = kDyldPath;
dyld_image_address = reinterpret_cast<mach_vm_address_t>( dyld_image_address = FromPointerCast<mach_vm_address_t>(
dyld_image_infos->dyldImageLoadAddress); dyld_image_infos->dyldImageLoadAddress);
} }

View File

@ -27,6 +27,7 @@
#include "snapshot/mac/process_types/internal.h" #include "snapshot/mac/process_types/internal.h"
#include "test/mac/dyld.h" #include "test/mac/dyld.h"
#include "util/mac/mac_util.h" #include "util/mac/mac_util.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/implicit_cast.h" #include "util/misc/implicit_cast.h"
namespace crashpad { namespace crashpad {
@ -81,7 +82,7 @@ TEST(ProcessTypes, DyldImagesSelf) {
ASSERT_EQ(kr, KERN_SUCCESS); ASSERT_EQ(kr, KERN_SUCCESS);
EXPECT_EQ(dyld_info.all_image_info_addr, EXPECT_EQ(dyld_info.all_image_info_addr,
reinterpret_cast<mach_vm_address_t>(self_image_infos)); FromPointerCast<mach_vm_address_t>(self_image_infos));
EXPECT_GT(dyld_info.all_image_info_size, 1u); EXPECT_GT(dyld_info.all_image_info_size, 1u);
// This field is only present in the OS X 10.7 SDK (at build time) and kernel // This field is only present in the OS X 10.7 SDK (at build time) and kernel

View File

@ -19,12 +19,13 @@
#include "base/logging.h" #include "base/logging.h"
#include "client/crashpad_client.h" #include "client/crashpad_client.h"
#include "util/file/file_io.h" #include "util/file/file_io.h"
#include "util/misc/from_pointer_cast.h"
#include "util/win/address_types.h" #include "util/win/address_types.h"
namespace { namespace {
__declspec(noinline) crashpad::WinVMAddress CurrentAddress() { __declspec(noinline) crashpad::WinVMAddress CurrentAddress() {
return reinterpret_cast<crashpad::WinVMAddress>(_ReturnAddress()); return crashpad::FromPointerCast<crashpad::WinVMAddress>(_ReturnAddress());
} }
} // namespace } // namespace

View File

@ -19,12 +19,13 @@
#include "client/crashpad_client.h" #include "client/crashpad_client.h"
#include "client/simulate_crash.h" #include "client/simulate_crash.h"
#include "util/file/file_io.h" #include "util/file/file_io.h"
#include "util/misc/from_pointer_cast.h"
#include "util/win/address_types.h" #include "util/win/address_types.h"
namespace { namespace {
__declspec(noinline) crashpad::WinVMAddress CurrentAddress() { __declspec(noinline) crashpad::WinVMAddress CurrentAddress() {
return reinterpret_cast<crashpad::WinVMAddress>(_ReturnAddress()); return crashpad::FromPointerCast<crashpad::WinVMAddress>(_ReturnAddress());
} }
} // namespace } // namespace

View File

@ -22,6 +22,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "client/crashpad_info.h" #include "client/crashpad_info.h"
#include "snapshot/win/pe_image_resource_reader.h" #include "snapshot/win/pe_image_resource_reader.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/pdb_structures.h" #include "util/misc/pdb_structures.h"
#include "util/win/process_structs.h" #include "util/win/process_structs.h"
@ -202,10 +203,8 @@ bool PEImageReader::VSFixedFileInfo(
WinVMAddress address; WinVMAddress address;
WinVMSize size; WinVMSize size;
const uint16_t vs_file_info_type = static_cast<uint16_t>(
reinterpret_cast<uintptr_t>(VS_FILE_INFO)); // RT_VERSION
if (!resource_reader.FindResourceByID( if (!resource_reader.FindResourceByID(
vs_file_info_type, FromPointerCast<uint16_t>(VS_FILE_INFO), // RT_VERSION
VS_VERSION_INFO, VS_VERSION_INFO,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
&address, &address,

View File

@ -22,6 +22,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "snapshot/win/process_reader_win.h" #include "snapshot/win/process_reader_win.h"
#include "test/errors.h" #include "test/errors.h"
#include "util/misc/from_pointer_cast.h"
#include "util/win/get_module_information.h" #include "util/win/get_module_information.h"
#include "util/win/module_version.h" #include "util/win/module_version.h"
#include "util/win/process_info.h" #include "util/win/process_info.h"
@ -44,7 +45,7 @@ TEST(PEImageReader, DebugDirectory) {
<< ErrorMessage("GetModuleInformation"); << ErrorMessage("GetModuleInformation");
EXPECT_EQ(module_info.lpBaseOfDll, self); EXPECT_EQ(module_info.lpBaseOfDll, self);
ASSERT_TRUE(pe_image_reader.Initialize(&process_reader, ASSERT_TRUE(pe_image_reader.Initialize(&process_reader,
reinterpret_cast<WinVMAddress>(self), FromPointerCast<WinVMAddress>(self),
module_info.SizeOfImage, module_info.SizeOfImage,
"self")); "self"));
UUID uuid; UUID uuid;
@ -139,7 +140,7 @@ TEST(PEImageReader, VSFixedFileInfo_OneModule) {
ProcessInfo::Module module; ProcessInfo::Module module;
module.name = kModuleName; module.name = kModuleName;
module.dll_base = reinterpret_cast<WinVMAddress>(module_info.lpBaseOfDll); module.dll_base = FromPointerCast<WinVMAddress>(module_info.lpBaseOfDll);
module.size = module_info.SizeOfImage; module.size = module_info.SizeOfImage;
TestVSFixedFileInfo(&process_reader, module, true); TestVSFixedFileInfo(&process_reader, module, true);

View File

@ -19,6 +19,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "test/win/win_multiprocess.h" #include "test/win/win_multiprocess.h"
#include "util/misc/from_pointer_cast.h"
#include "util/synchronization/semaphore.h" #include "util/synchronization/semaphore.h"
#include "util/thread/thread.h" #include "util/thread/thread.h"
#include "util/win/scoped_process_suspend.h" #include "util/win/scoped_process_suspend.h"
@ -42,10 +43,8 @@ TEST(ProcessReaderWin, SelfBasic) {
const char kTestMemory[] = "Some test memory"; const char kTestMemory[] = "Some test memory";
char buffer[arraysize(kTestMemory)]; char buffer[arraysize(kTestMemory)];
ASSERT_TRUE( ASSERT_TRUE(process_reader.ReadMemory(
process_reader.ReadMemory(reinterpret_cast<uintptr_t>(kTestMemory), reinterpret_cast<uintptr_t>(kTestMemory), sizeof(kTestMemory), &buffer));
sizeof(kTestMemory),
&buffer));
EXPECT_STREQ(kTestMemory, buffer); EXPECT_STREQ(kTestMemory, buffer);
} }
@ -78,7 +77,7 @@ class ProcessReaderChild final : public WinMultiprocess {
} }
void WinMultiprocessChild() override { void WinMultiprocessChild() override {
WinVMAddress address = reinterpret_cast<WinVMAddress>(kTestMemory); WinVMAddress address = FromPointerCast<WinVMAddress>(kTestMemory);
CheckedWriteFile(WritePipeHandle(), &address, sizeof(address)); CheckedWriteFile(WritePipeHandle(), &address, sizeof(address));
// Wait for the parent to signal that it's OK to exit by closing its end of // Wait for the parent to signal that it's OK to exit by closing its end of

View File

@ -26,6 +26,7 @@
#include "snapshot/win/exception_snapshot_win.h" #include "snapshot/win/exception_snapshot_win.h"
#include "snapshot/win/memory_snapshot_win.h" #include "snapshot/win/memory_snapshot_win.h"
#include "snapshot/win/module_snapshot_win.h" #include "snapshot/win/module_snapshot_win.h"
#include "util/misc/from_pointer_cast.h"
#include "util/win/nt_internals.h" #include "util/win/nt_internals.h"
#include "util/win/registration_protocol_win.h" #include "util/win/registration_protocol_win.h"
#include "util/win/time.h" #include "util/win/time.h"
@ -295,7 +296,7 @@ void ProcessSnapshotWin::InitializeUnloadedModules() {
} }
const WinVMAddress address_in_target_process = const WinVMAddress address_in_target_process =
reinterpret_cast<WinVMAddress>(event_trace_address); FromPointerCast<WinVMAddress>(event_trace_address);
Traits::Pointer pointer_to_array; Traits::Pointer pointer_to_array;
if (!process_reader_.ReadMemory(address_in_target_process, if (!process_reader_.ReadMemory(address_in_target_process,

View File

@ -25,6 +25,7 @@
#include "base/mac/scoped_mach_vm.h" #include "base/mac/scoped_mach_vm.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "test/mac/mach_errors.h" #include "test/mac/mach_errors.h"
#include "util/misc/from_pointer_cast.h"
namespace crashpad { namespace crashpad {
namespace test { namespace test {
@ -165,7 +166,7 @@ TEST(TaskMemory, ReadSelfUnmapped) {
bool ReadCStringSelf(TaskMemory* memory, bool ReadCStringSelf(TaskMemory* memory,
const char* pointer, const char* pointer,
std::string* result) { std::string* result) {
return memory->ReadCString(reinterpret_cast<mach_vm_address_t>(pointer), return memory->ReadCString(FromPointerCast<mach_vm_address_t>(pointer),
result); result);
} }
@ -272,7 +273,7 @@ bool ReadCStringSizeLimitedSelf(TaskMemory* memory,
size_t size, size_t size,
std::string* result) { std::string* result) {
return memory->ReadCStringSizeLimited( return memory->ReadCStringSizeLimited(
reinterpret_cast<mach_vm_address_t>(pointer), size, result); FromPointerCast<mach_vm_address_t>(pointer), size, result);
} }
TEST(TaskMemory, ReadCStringSizeLimited_ConstCharEmpty) { TEST(TaskMemory, ReadCStringSizeLimited_ConstCharEmpty) {
@ -462,7 +463,7 @@ TEST(TaskMemory, MappedMemoryDeallocates) {
static const char kTestBuffer[] = "hello!"; static const char kTestBuffer[] = "hello!";
mach_vm_address_t test_address = mach_vm_address_t test_address =
reinterpret_cast<mach_vm_address_t>(&kTestBuffer); FromPointerCast<mach_vm_address_t>(&kTestBuffer);
ASSERT_TRUE((mapped = memory.ReadMapped(test_address, sizeof(kTestBuffer)))); ASSERT_TRUE((mapped = memory.ReadMapped(test_address, sizeof(kTestBuffer))));
EXPECT_EQ(memcmp(kTestBuffer, mapped->data(), sizeof(kTestBuffer)), 0); EXPECT_EQ(memcmp(kTestBuffer, mapped->data(), sizeof(kTestBuffer)), 0);
@ -477,7 +478,7 @@ TEST(TaskMemory, MappedMemoryDeallocates) {
// deallocated. // deallocated.
const size_t kBigSize = 4 * PAGE_SIZE; const size_t kBigSize = 4 * PAGE_SIZE;
std::unique_ptr<char[]> big_buffer(new char[kBigSize]); std::unique_ptr<char[]> big_buffer(new char[kBigSize]);
test_address = reinterpret_cast<mach_vm_address_t>(&big_buffer[0]); test_address = FromPointerCast<mach_vm_address_t>(&big_buffer[0]);
ASSERT_TRUE((mapped = memory.ReadMapped(test_address, kBigSize))); ASSERT_TRUE((mapped = memory.ReadMapped(test_address, kBigSize)));
mapped_address = reinterpret_cast<vm_address_t>(mapped->data()); mapped_address = reinterpret_cast<vm_address_t>(mapped->data());
@ -499,7 +500,7 @@ TEST(TaskMemory, MappedMemoryReadCString) {
static const char kTestBuffer[] = "0\0" "2\0" "45\0" "789"; static const char kTestBuffer[] = "0\0" "2\0" "45\0" "789";
const mach_vm_address_t kTestAddress = const mach_vm_address_t kTestAddress =
reinterpret_cast<mach_vm_address_t>(&kTestBuffer); FromPointerCast<mach_vm_address_t>(&kTestBuffer);
ASSERT_TRUE((mapped = memory.ReadMapped(kTestAddress, 10))); ASSERT_TRUE((mapped = memory.ReadMapped(kTestAddress, 10)));
std::string string; std::string string;

View File

@ -20,6 +20,8 @@
#include <cstddef> #include <cstddef>
#include <type_traits> #include <type_traits>
#include "base/numerics/safe_conversions.h"
namespace crashpad { namespace crashpad {
#if DOXYGEN #if DOXYGEN
@ -29,37 +31,29 @@ namespace crashpad {
//! Compared to `reinterpret_cast<>()`, FromPointerCast<>() defines whether a //! Compared to `reinterpret_cast<>()`, FromPointerCast<>() defines whether a
//! pointer type is sign-extended or zero-extended. Casts to signed integral //! pointer type is sign-extended or zero-extended. Casts to signed integral
//! types are sign-extended. Casts to unsigned integral types are zero-extended. //! types are sign-extended. Casts to unsigned integral types are zero-extended.
//!
//! Use FromPointerCast<>() instead of `reinterpret_cast<>()` when casting a
//! pointer to an integral type that may not be the same width as a pointer.
//! There is no need to prefer FromPointerCast<>() when casting to an integral
//! type thats definitely the same width as a pointer, such as `uintptr_t` and
//! `intptr_t`.
template <typename To, typename From> template <typename To, typename From>
FromPointerCast(const From from) { FromPointerCast(From from) {
return reinterpret_cast<To>(from); return reinterpret_cast<To>(from);
} }
#else // DOXYGEN #else // DOXYGEN
// Cast std::nullptr_t to any pointer type. // Cast std::nullptr_t to any type.
// //
// In C++14, the nullptr_t check could use std::is_null_pointer<From>::type // In C++14, the nullptr_t check could use std::is_null_pointer<From>::value
// instead of the is_same<remove_cv<From>::type, nullptr_t>::type construct. // instead of the is_same<remove_cv<From>::type, nullptr_t>::type construct.
template <typename To, typename From> template <typename To, typename From>
typename std::enable_if< typename std::enable_if<
std::is_same<typename std::remove_cv<From>::type, std::nullptr_t>::value && std::is_same<typename std::remove_cv<From>::type, std::nullptr_t>::value,
std::is_pointer<To>::value,
To>::type To>::type
FromPointerCast(const From& from) { FromPointerCast(From) {
return static_cast<To>(from); return To();
}
// Cast std::nullptr_t to any integral type.
//
// In C++14, the nullptr_t check could use std::is_null_pointer<From>::type
// instead of the is_same<remove_cv<From>::type, nullptr_t>::type construct.
template <typename To, typename From>
typename std::enable_if<
std::is_same<typename std::remove_cv<From>::type, std::nullptr_t>::value &&
std::is_integral<To>::value,
To>::type
FromPointerCast(const From& from) {
return reinterpret_cast<To>(from);
} }
// Cast a pointer to any other pointer type. // Cast a pointer to any other pointer type.
@ -67,7 +61,7 @@ template <typename To, typename From>
typename std::enable_if<std::is_pointer<From>::value && typename std::enable_if<std::is_pointer<From>::value &&
std::is_pointer<To>::value, std::is_pointer<To>::value,
To>::type To>::type
FromPointerCast(const From from) { FromPointerCast(From from) {
return reinterpret_cast<To>(from); return reinterpret_cast<To>(from);
} }
@ -77,11 +71,21 @@ template <typename To, typename From>
typename std::enable_if<std::is_pointer<From>::value && typename std::enable_if<std::is_pointer<From>::value &&
std::is_integral<To>::value, std::is_integral<To>::value,
To>::type To>::type
FromPointerCast(const From from) { FromPointerCast(From from) {
return static_cast<To>( const auto intermediate =
reinterpret_cast<typename std::conditional<std::is_signed<To>::value, reinterpret_cast<typename std::conditional<std::is_signed<To>::value,
intptr_t, intptr_t,
uintptr_t>::type>(from)); uintptr_t>::type>(from);
if (sizeof(To) >= sizeof(From)) {
// If the destination integral type is at least as wide as the source
// pointer type, use static_cast<>() and just return it.
return static_cast<To>(intermediate);
}
// If the destination integral type is narrower than the source pointer type,
// use checked_cast<>().
return base::checked_cast<To>(intermediate);
} }
#endif // DOXYGEN #endif // DOXYGEN

View File

@ -21,6 +21,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "test/gtest_death_check.h"
namespace crashpad { namespace crashpad {
namespace test { namespace test {
@ -185,6 +186,76 @@ TEST(FromPointerCast, FromFunctionPointer) {
MaybeRemoveVolatile(reinterpret_cast<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
} // namespace test } // namespace test
} // namespace crashpad } // namespace crashpad

View File

@ -17,6 +17,7 @@
#include <stdint.h> #include <stdint.h>
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "util/misc/from_pointer_cast.h"
namespace crashpad { namespace crashpad {
@ -26,7 +27,7 @@ namespace crashpad {
// back to the same HANDLE value. // back to the same HANDLE value.
int HandleToInt(HANDLE handle) { int HandleToInt(HANDLE handle) {
return base::checked_cast<int>(reinterpret_cast<intptr_t>(handle)); return FromPointerCast<int>(handle);
} }
HANDLE IntToHandle(int handle_int) { HANDLE IntToHandle(int handle_int) {

View File

@ -28,6 +28,7 @@
#include "base/process/memory.h" #include "base/process/memory.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "util/misc/from_pointer_cast.h"
#include "util/numeric/safe_assignment.h" #include "util/numeric/safe_assignment.h"
#include "util/win/get_function.h" #include "util/win/get_function.h"
#include "util/win/handle.h" #include "util/win/handle.h"
@ -133,7 +134,7 @@ bool RegionIsAccessible(const MEMORY_BASIC_INFORMATION64& memory_info) {
MEMORY_BASIC_INFORMATION64 MemoryBasicInformationToMemoryBasicInformation64( MEMORY_BASIC_INFORMATION64 MemoryBasicInformationToMemoryBasicInformation64(
const MEMORY_BASIC_INFORMATION& mbi) { const MEMORY_BASIC_INFORMATION& mbi) {
MEMORY_BASIC_INFORMATION64 mbi64 = {0}; MEMORY_BASIC_INFORMATION64 mbi64 = {0};
mbi64.BaseAddress = reinterpret_cast<ULONGLONG>(mbi.BaseAddress); mbi64.BaseAddress = FromPointerCast<ULONGLONG>(mbi.BaseAddress);
mbi64.AllocationBase = reinterpret_cast<ULONGLONG>(mbi.AllocationBase); mbi64.AllocationBase = reinterpret_cast<ULONGLONG>(mbi.AllocationBase);
mbi64.AllocationProtect = mbi.AllocationProtect; mbi64.AllocationProtect = mbi.AllocationProtect;
mbi64.RegionSize = mbi.RegionSize; mbi64.RegionSize = mbi.RegionSize;

View File

@ -30,6 +30,7 @@
#include "test/test_paths.h" #include "test/test_paths.h"
#include "test/win/child_launcher.h" #include "test/win/child_launcher.h"
#include "util/file/file_io.h" #include "util/file/file_io.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/random_string.h" #include "util/misc/random_string.h"
#include "util/misc/uuid.h" #include "util/misc/uuid.h"
#include "util/win/command_line.h" #include "util/win/command_line.h"
@ -125,7 +126,7 @@ TEST(ProcessInfo, Self) {
// Find something we know is a code address and confirm expected memory // Find something we know is a code address and confirm expected memory
// information settings. // information settings.
VerifyAddressInInCodePage(process_info, VerifyAddressInInCodePage(process_info,
reinterpret_cast<WinVMAddress>(_ReturnAddress())); FromPointerCast<WinVMAddress>(_ReturnAddress()));
} }
void TestOtherProcess(const base::string16& directory_modification) { void TestOtherProcess(const base::string16& directory_modification) {
@ -640,7 +641,7 @@ TEST(ProcessInfo, OutOfRangeCheck) {
EXPECT_TRUE( EXPECT_TRUE(
info.LoggingRangeIsFullyReadable(CheckedRange<WinVMAddress, WinVMSize>( info.LoggingRangeIsFullyReadable(CheckedRange<WinVMAddress, WinVMSize>(
reinterpret_cast<WinVMAddress>(safe_memory.get()), kAllocationSize))); FromPointerCast<WinVMAddress>(safe_memory.get()), kAllocationSize)));
EXPECT_FALSE(info.LoggingRangeIsFullyReadable( EXPECT_FALSE(info.LoggingRangeIsFullyReadable(
CheckedRange<WinVMAddress, WinVMSize>(0, 1024))); CheckedRange<WinVMAddress, WinVMSize>(0, 1024)));
} }