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 <regex> 10 #include <string> 11 12 #include "gwp_asan/common.h" 13 #include "gwp_asan/crash_handler.h" 14 #include "gwp_asan/tests/harness.h" 15 16 TEST_P(BacktraceGuardedPoolAllocatorDeathTest, DoubleFree) { 17 void *Ptr = AllocateMemory(GPA); 18 DeallocateMemory(GPA, Ptr); 19 20 std::string DeathRegex = "Double Free.*DeallocateMemory2.*"; 21 DeathRegex.append("was deallocated.*DeallocateMemory[^2].*"); 22 DeathRegex.append("was allocated.*AllocateMemory"); 23 if (!Recoverable) { 24 ASSERT_DEATH(DeallocateMemory2(GPA, Ptr), DeathRegex); 25 return; 26 } 27 28 // For recoverable, assert that DeallocateMemory2() doesn't crash. 29 DeallocateMemory2(GPA, Ptr); 30 // Fuchsia's zxtest doesn't have an EXPECT_THAT(testing::MatchesRegex(), ...), 31 // so check the regex manually. 32 EXPECT_TRUE(std::regex_search( 33 GetOutputBuffer(), 34 std::basic_regex(DeathRegex, std::regex_constants::extended))) 35 << "Regex \"" << DeathRegex 36 << "\" was not found in input:\n============\n" 37 << GetOutputBuffer() << "\n============"; 38 } 39 40 TEST_P(BacktraceGuardedPoolAllocatorDeathTest, UseAfterFree) { 41 #if defined(__linux__) && __ARM_ARCH == 7 42 // Incomplete backtrace on Armv7 Linux 43 GTEST_SKIP(); 44 #endif 45 46 void *Ptr = AllocateMemory(GPA); 47 DeallocateMemory(GPA, Ptr); 48 49 std::string DeathRegex = "Use After Free.*TouchMemory.*"; 50 DeathRegex.append("was deallocated.*DeallocateMemory[^2].*"); 51 DeathRegex.append("was allocated.*AllocateMemory"); 52 53 if (!Recoverable) { 54 ASSERT_DEATH(TouchMemory(Ptr), DeathRegex); 55 return; 56 } 57 58 // For recoverable, assert that TouchMemory() doesn't crash. 59 TouchMemory(Ptr); 60 // Fuchsia's zxtest doesn't have an EXPECT_THAT(testing::MatchesRegex(), ...), 61 // so check the regex manually. 62 EXPECT_TRUE(std::regex_search( 63 GetOutputBuffer(), 64 std::basic_regex(DeathRegex, std::regex_constants::extended))) 65 << "Regex \"" << DeathRegex 66 << "\" was not found in input:\n============\n" 67 << GetOutputBuffer() << "\n============"; 68 ; 69 } 70 71 INSTANTIATE_TEST_SUITE_P(RecoverableSignalDeathTest, 72 BacktraceGuardedPoolAllocatorDeathTest, 73 /* Recoverable */ testing::Bool()); 74 75 TEST(Backtrace, Short) { 76 gwp_asan::AllocationMetadata Meta; 77 Meta.AllocationTrace.RecordBacktrace( 78 [](uintptr_t *TraceBuffer, size_t /* Size */) -> size_t { 79 TraceBuffer[0] = 123u; 80 TraceBuffer[1] = 321u; 81 return 2u; 82 }); 83 uintptr_t TraceOutput[2] = {}; 84 EXPECT_EQ(2u, __gwp_asan_get_allocation_trace(&Meta, TraceOutput, 2)); 85 EXPECT_EQ(TraceOutput[0], 123u); 86 EXPECT_EQ(TraceOutput[1], 321u); 87 } 88 89 TEST(Backtrace, ExceedsStorableLength) { 90 gwp_asan::AllocationMetadata Meta; 91 Meta.AllocationTrace.RecordBacktrace( 92 [](uintptr_t *TraceBuffer, size_t Size) -> size_t { 93 // Need to inintialise the elements that will be packed. 94 memset(TraceBuffer, 0u, Size * sizeof(*TraceBuffer)); 95 96 // Indicate that there were more frames, and we just didn't have enough 97 // room to store them. 98 return Size * 2; 99 }); 100 // Retrieve a frame from the collected backtrace, make sure it works E2E. 101 uintptr_t TraceOutput; 102 EXPECT_EQ(gwp_asan::AllocationMetadata::kMaxTraceLengthToCollect, 103 __gwp_asan_get_allocation_trace(&Meta, &TraceOutput, 1)); 104 } 105 106 TEST(Backtrace, ExceedsRetrievableAllocLength) { 107 gwp_asan::AllocationMetadata Meta; 108 constexpr size_t kNumFramesToStore = 3u; 109 Meta.AllocationTrace.RecordBacktrace( 110 [](uintptr_t *TraceBuffer, size_t /* Size */) -> size_t { 111 memset(TraceBuffer, kNumFramesToStore, 112 kNumFramesToStore * sizeof(*TraceBuffer)); 113 return kNumFramesToStore; 114 }); 115 uintptr_t TraceOutput; 116 // Ask for one element, get told that there's `kNumFramesToStore` available. 117 EXPECT_EQ(kNumFramesToStore, 118 __gwp_asan_get_allocation_trace(&Meta, &TraceOutput, 1)); 119 } 120 121 TEST(Backtrace, ExceedsRetrievableDeallocLength) { 122 gwp_asan::AllocationMetadata Meta; 123 constexpr size_t kNumFramesToStore = 3u; 124 Meta.DeallocationTrace.RecordBacktrace( 125 [](uintptr_t *TraceBuffer, size_t /* Size */) -> size_t { 126 memset(TraceBuffer, kNumFramesToStore, 127 kNumFramesToStore * sizeof(*TraceBuffer)); 128 return kNumFramesToStore; 129 }); 130 uintptr_t TraceOutput; 131 // Ask for one element, get told that there's `kNumFramesToStore` available. 132 EXPECT_EQ(kNumFramesToStore, 133 __gwp_asan_get_deallocation_trace(&Meta, &TraceOutput, 1)); 134 } 135