1 //===-- backtrace.cpp -------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
12 #include "gwp_asan/common.h"
13 #include "gwp_asan/crash_handler.h"
14 #include "gwp_asan/tests/harness.h"
16 TEST_P(BacktraceGuardedPoolAllocatorDeathTest
, DoubleFree
) {
17 void *Ptr
= AllocateMemory(GPA
);
18 DeallocateMemory(GPA
, Ptr
);
20 std::string DeathRegex
= "Double Free.*DeallocateMemory2.*";
21 DeathRegex
.append("was deallocated.*DeallocateMemory[^2].*");
22 DeathRegex
.append("was allocated.*AllocateMemory");
24 ASSERT_DEATH(DeallocateMemory2(GPA
, Ptr
), DeathRegex
);
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(
34 std::basic_regex(DeathRegex
, std::regex_constants::extended
)))
35 << "Regex \"" << DeathRegex
36 << "\" was not found in input:\n============\n"
37 << GetOutputBuffer() << "\n============";
40 TEST_P(BacktraceGuardedPoolAllocatorDeathTest
, UseAfterFree
) {
41 #if defined(__linux__) && __ARM_ARCH == 7
42 // Incomplete backtrace on Armv7 Linux
46 void *Ptr
= AllocateMemory(GPA
);
47 DeallocateMemory(GPA
, Ptr
);
49 std::string DeathRegex
= "Use After Free.*TouchMemory.*";
50 DeathRegex
.append("was deallocated.*DeallocateMemory[^2].*");
51 DeathRegex
.append("was allocated.*AllocateMemory");
54 ASSERT_DEATH(TouchMemory(Ptr
), DeathRegex
);
58 // For recoverable, assert that TouchMemory() doesn't crash.
60 // Fuchsia's zxtest doesn't have an EXPECT_THAT(testing::MatchesRegex(), ...),
61 // so check the regex manually.
62 EXPECT_TRUE(std::regex_search(
64 std::basic_regex(DeathRegex
, std::regex_constants::extended
)))
65 << "Regex \"" << DeathRegex
66 << "\" was not found in input:\n============\n"
67 << GetOutputBuffer() << "\n============";
71 INSTANTIATE_TEST_SUITE_P(RecoverableSignalDeathTest
,
72 BacktraceGuardedPoolAllocatorDeathTest
,
73 /* Recoverable */ testing::Bool());
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;
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);
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
));
96 // Indicate that there were more frames, and we just didn't have enough
97 // room to store them.
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));
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
;
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));
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
;
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));