1 //===-- crash_handler_api.cpp -----------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "gwp_asan/crash_handler.h" 10 #include "gwp_asan/guarded_pool_allocator.h" 11 #include "gwp_asan/stack_trace_compressor.h" 12 #include "gwp_asan/tests/harness.h" 13 14 using Error = gwp_asan::Error; 15 using GuardedPoolAllocator = gwp_asan::GuardedPoolAllocator; 16 using AllocationMetadata = gwp_asan::AllocationMetadata; 17 using AllocatorState = gwp_asan::AllocatorState; 18 19 class CrashHandlerAPITest : public ::testing::Test { 20 public: 21 void SetUp() override { setupState(); } 22 23 protected: 24 size_t metadata(uintptr_t Addr, uintptr_t Size, bool IsDeallocated) { 25 // Should only be allocating the 0x3000, 0x5000, 0x7000, 0x9000 pages. 26 EXPECT_GE(Addr, 0x3000u); 27 EXPECT_LT(Addr, 0xa000u); 28 29 size_t Slot = State.getNearestSlot(Addr); 30 31 Metadata[Slot].Addr = Addr; 32 Metadata[Slot].Size = Size; 33 Metadata[Slot].IsDeallocated = IsDeallocated; 34 Metadata[Slot].AllocationTrace.ThreadID = 123; 35 Metadata[Slot].DeallocationTrace.ThreadID = 321; 36 setupBacktraces(&Metadata[Slot]); 37 38 return Slot; 39 } 40 41 void setupState() { 42 State.GuardedPagePool = 0x2000; 43 State.GuardedPagePoolEnd = 0xb000; 44 State.MaxSimultaneousAllocations = 4; // 0x3000, 0x5000, 0x7000, 0x9000. 45 State.PageSize = 0x1000; 46 } 47 48 void setupBacktraces(AllocationMetadata *Meta) { 49 Meta->AllocationTrace.TraceSize = gwp_asan::compression::pack( 50 BacktraceConstants, kNumBacktraceConstants, 51 Meta->AllocationTrace.CompressedTrace, 52 AllocationMetadata::kStackFrameStorageBytes); 53 54 if (Meta->IsDeallocated) 55 Meta->DeallocationTrace.TraceSize = gwp_asan::compression::pack( 56 BacktraceConstants, kNumBacktraceConstants, 57 Meta->DeallocationTrace.CompressedTrace, 58 AllocationMetadata::kStackFrameStorageBytes); 59 } 60 61 void checkBacktrace(const AllocationMetadata *Meta, bool IsDeallocated) { 62 uintptr_t Buffer[kNumBacktraceConstants]; 63 size_t NumBacktraceConstants = kNumBacktraceConstants; 64 EXPECT_EQ(NumBacktraceConstants, 65 __gwp_asan_get_allocation_trace(&State, Meta, Buffer, 66 kNumBacktraceConstants)); 67 for (size_t i = 0; i < kNumBacktraceConstants; ++i) 68 EXPECT_EQ(Buffer[i], BacktraceConstants[i]); 69 70 if (IsDeallocated) { 71 EXPECT_EQ(NumBacktraceConstants, 72 __gwp_asan_get_deallocation_trace(&State, Meta, Buffer, 73 kNumBacktraceConstants)); 74 for (size_t i = 0; i < kNumBacktraceConstants; ++i) 75 EXPECT_EQ(Buffer[i], BacktraceConstants[i]); 76 } 77 } 78 79 void checkMetadata(size_t Index, uintptr_t ErrorPtr) { 80 const AllocationMetadata *Meta = 81 __gwp_asan_get_metadata(&State, Metadata, ErrorPtr); 82 EXPECT_NE(nullptr, Meta); 83 EXPECT_EQ(Metadata[Index].Addr, 84 __gwp_asan_get_allocation_address(&State, Meta)); 85 EXPECT_EQ(Metadata[Index].Size, 86 __gwp_asan_get_allocation_size(&State, Meta)); 87 EXPECT_EQ(Metadata[Index].AllocationTrace.ThreadID, 88 __gwp_asan_get_allocation_thread_id(&State, Meta)); 89 90 bool IsDeallocated = __gwp_asan_is_deallocated(&State, Meta); 91 EXPECT_EQ(Metadata[Index].IsDeallocated, IsDeallocated); 92 checkBacktrace(Meta, IsDeallocated); 93 94 if (!IsDeallocated) 95 return; 96 97 EXPECT_EQ(Metadata[Index].DeallocationTrace.ThreadID, 98 __gwp_asan_get_deallocation_thread_id(&State, Meta)); 99 } 100 101 static constexpr size_t kNumBacktraceConstants = 4; 102 static uintptr_t BacktraceConstants[kNumBacktraceConstants]; 103 AllocatorState State = {}; 104 AllocationMetadata Metadata[4] = {}; 105 }; 106 107 uintptr_t CrashHandlerAPITest::BacktraceConstants[kNumBacktraceConstants] = { 108 0xdeadbeef, 0xdeadc0de, 0xbadc0ffee, 0xcafef00d}; 109 110 TEST_F(CrashHandlerAPITest, PointerNotMine) { 111 uintptr_t UnknownPtr = reinterpret_cast<uintptr_t>(&State); 112 113 EXPECT_FALSE(__gwp_asan_error_is_mine(&State, 0)); 114 EXPECT_FALSE(__gwp_asan_error_is_mine(&State, UnknownPtr)); 115 116 EXPECT_EQ(Error::UNKNOWN, __gwp_asan_diagnose_error(&State, Metadata, 0)); 117 EXPECT_EQ(Error::UNKNOWN, 118 __gwp_asan_diagnose_error(&State, Metadata, UnknownPtr)); 119 120 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, 0)); 121 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, UnknownPtr)); 122 } 123 124 TEST_F(CrashHandlerAPITest, PointerNotAllocated) { 125 uintptr_t FailureAddress = 0x9000; 126 127 EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); 128 EXPECT_EQ(Error::UNKNOWN, 129 __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); 130 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); 131 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, FailureAddress)); 132 } 133 134 TEST_F(CrashHandlerAPITest, DoubleFree) { 135 size_t Index = 136 metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true); 137 uintptr_t FailureAddress = 0x7000; 138 139 State.FailureType = Error::DOUBLE_FREE; 140 State.FailureAddress = FailureAddress; 141 142 EXPECT_TRUE(__gwp_asan_error_is_mine(&State)); 143 EXPECT_EQ(Error::DOUBLE_FREE, 144 __gwp_asan_diagnose_error(&State, Metadata, 0x0)); 145 EXPECT_EQ(FailureAddress, __gwp_asan_get_internal_crash_address(&State)); 146 checkMetadata(Index, FailureAddress); 147 } 148 149 TEST_F(CrashHandlerAPITest, InvalidFree) { 150 size_t Index = 151 metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ false); 152 uintptr_t FailureAddress = 0x7001; 153 154 State.FailureType = Error::INVALID_FREE; 155 State.FailureAddress = FailureAddress; 156 157 EXPECT_TRUE(__gwp_asan_error_is_mine(&State)); 158 EXPECT_EQ(Error::INVALID_FREE, 159 __gwp_asan_diagnose_error(&State, Metadata, 0x0)); 160 EXPECT_EQ(FailureAddress, __gwp_asan_get_internal_crash_address(&State)); 161 checkMetadata(Index, FailureAddress); 162 } 163 164 TEST_F(CrashHandlerAPITest, InvalidFreeNoMetadata) { 165 uintptr_t FailureAddress = 0x7001; 166 167 State.FailureType = Error::INVALID_FREE; 168 State.FailureAddress = FailureAddress; 169 170 EXPECT_TRUE(__gwp_asan_error_is_mine(&State)); 171 EXPECT_EQ(Error::INVALID_FREE, 172 __gwp_asan_diagnose_error(&State, Metadata, 0x0)); 173 EXPECT_EQ(FailureAddress, __gwp_asan_get_internal_crash_address(&State)); 174 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, FailureAddress)); 175 } 176 177 TEST_F(CrashHandlerAPITest, UseAfterFree) { 178 size_t Index = 179 metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true); 180 uintptr_t FailureAddress = 0x7001; 181 182 EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); 183 EXPECT_EQ(Error::USE_AFTER_FREE, 184 __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); 185 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); 186 checkMetadata(Index, FailureAddress); 187 } 188 189 TEST_F(CrashHandlerAPITest, BufferOverflow) { 190 size_t Index = 191 metadata(/* Addr */ 0x5f00, /* Size */ 0x100, /* IsDeallocated */ false); 192 uintptr_t FailureAddress = 0x6000; 193 194 EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); 195 EXPECT_EQ(Error::BUFFER_OVERFLOW, 196 __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); 197 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); 198 checkMetadata(Index, FailureAddress); 199 } 200 201 TEST_F(CrashHandlerAPITest, BufferUnderflow) { 202 size_t Index = 203 metadata(/* Addr */ 0x3000, /* Size */ 0x10, /* IsDeallocated*/ false); 204 uintptr_t FailureAddress = 0x2fff; 205 206 EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); 207 EXPECT_EQ(Error::BUFFER_UNDERFLOW, 208 __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); 209 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); 210 checkMetadata(Index, FailureAddress); 211 } 212