1 //===-- backtrace.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 <string> 10 11 #include "gwp_asan/crash_handler.h" 12 #include "gwp_asan/tests/harness.h" 13 14 // Optnone to ensure that the calls to these functions are not optimized away, 15 // as we're looking for them in the backtraces. 16 __attribute((optnone)) void * 17 AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA) { 18 return GPA.allocate(1); 19 } 20 __attribute((optnone)) void 21 DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr) { 22 GPA.deallocate(Ptr); 23 } 24 __attribute((optnone)) void 25 DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr) { 26 GPA.deallocate(Ptr); 27 } 28 __attribute__((optnone)) void TouchMemory(void *Ptr) { 29 *(reinterpret_cast<volatile char *>(Ptr)) = 7; 30 } 31 32 TEST_F(BacktraceGuardedPoolAllocator, DoubleFree) { 33 void *Ptr = AllocateMemory(GPA); 34 DeallocateMemory(GPA, Ptr); 35 36 std::string DeathRegex = "Double Free.*"; 37 DeathRegex.append("DeallocateMemory2.*"); 38 39 DeathRegex.append("was deallocated.*"); 40 DeathRegex.append("DeallocateMemory.*"); 41 42 DeathRegex.append("was allocated.*"); 43 DeathRegex.append("AllocateMemory.*"); 44 ASSERT_DEATH(DeallocateMemory2(GPA, Ptr), DeathRegex); 45 } 46 47 TEST_F(BacktraceGuardedPoolAllocator, UseAfterFree) { 48 void *Ptr = AllocateMemory(GPA); 49 DeallocateMemory(GPA, Ptr); 50 51 std::string DeathRegex = "Use After Free.*"; 52 DeathRegex.append("TouchMemory.*"); 53 54 DeathRegex.append("was deallocated.*"); 55 DeathRegex.append("DeallocateMemory.*"); 56 57 DeathRegex.append("was allocated.*"); 58 DeathRegex.append("AllocateMemory.*"); 59 ASSERT_DEATH(TouchMemory(Ptr), DeathRegex); 60 } 61 62 TEST(Backtrace, Short) { 63 gwp_asan::AllocationMetadata Meta; 64 Meta.AllocationTrace.RecordBacktrace( 65 [](uintptr_t *TraceBuffer, size_t /* Size */) -> size_t { 66 TraceBuffer[0] = 123u; 67 TraceBuffer[1] = 321u; 68 return 2u; 69 }); 70 uintptr_t TraceOutput[2] = {}; 71 EXPECT_EQ(2u, __gwp_asan_get_allocation_trace(&Meta, TraceOutput, 2)); 72 EXPECT_EQ(TraceOutput[0], 123u); 73 EXPECT_EQ(TraceOutput[1], 321u); 74 } 75 76 TEST(Backtrace, ExceedsStorableLength) { 77 gwp_asan::AllocationMetadata Meta; 78 Meta.AllocationTrace.RecordBacktrace( 79 [](uintptr_t * /* TraceBuffer */, size_t /* Size */) -> size_t { 80 return SIZE_MAX; // Wow, that's big! 81 }); 82 uintptr_t TraceOutput; 83 EXPECT_EQ(1u, __gwp_asan_get_allocation_trace(&Meta, &TraceOutput, 1)); 84 } 85