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 EXPECT_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 EXPECT_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 TEST(Backtrace
, Short
) {
72 gwp_asan::AllocationMetadata Meta
;
73 Meta
.AllocationTrace
.RecordBacktrace(
74 [](uintptr_t *TraceBuffer
, size_t /* Size */) -> size_t {
75 TraceBuffer
[0] = 123u;
76 TraceBuffer
[1] = 321u;
79 uintptr_t TraceOutput
[2] = {};
80 EXPECT_EQ(2u, __gwp_asan_get_allocation_trace(&Meta
, TraceOutput
, 2));
81 EXPECT_EQ(TraceOutput
[0], 123u);
82 EXPECT_EQ(TraceOutput
[1], 321u);
85 TEST(Backtrace
, ExceedsStorableLength
) {
86 gwp_asan::AllocationMetadata Meta
;
87 Meta
.AllocationTrace
.RecordBacktrace(
88 [](uintptr_t *TraceBuffer
, size_t Size
) -> size_t {
89 // Need to inintialise the elements that will be packed.
90 memset(TraceBuffer
, 0u, Size
* sizeof(*TraceBuffer
));
92 // Indicate that there were more frames, and we just didn't have enough
93 // room to store them.
96 // Retrieve a frame from the collected backtrace, make sure it works E2E.
97 uintptr_t TraceOutput
;
98 EXPECT_EQ(gwp_asan::AllocationMetadata::kMaxTraceLengthToCollect
,
99 __gwp_asan_get_allocation_trace(&Meta
, &TraceOutput
, 1));
102 TEST(Backtrace
, ExceedsRetrievableAllocLength
) {
103 gwp_asan::AllocationMetadata Meta
;
104 constexpr size_t kNumFramesToStore
= 3u;
105 Meta
.AllocationTrace
.RecordBacktrace(
106 [](uintptr_t *TraceBuffer
, size_t /* Size */) -> size_t {
107 memset(TraceBuffer
, kNumFramesToStore
,
108 kNumFramesToStore
* sizeof(*TraceBuffer
));
109 return kNumFramesToStore
;
111 uintptr_t TraceOutput
;
112 // Ask for one element, get told that there's `kNumFramesToStore` available.
113 EXPECT_EQ(kNumFramesToStore
,
114 __gwp_asan_get_allocation_trace(&Meta
, &TraceOutput
, 1));
117 TEST(Backtrace
, ExceedsRetrievableDeallocLength
) {
118 gwp_asan::AllocationMetadata Meta
;
119 constexpr size_t kNumFramesToStore
= 3u;
120 Meta
.DeallocationTrace
.RecordBacktrace(
121 [](uintptr_t *TraceBuffer
, size_t /* Size */) -> size_t {
122 memset(TraceBuffer
, kNumFramesToStore
,
123 kNumFramesToStore
* sizeof(*TraceBuffer
));
124 return kNumFramesToStore
;
126 uintptr_t TraceOutput
;
127 // Ask for one element, get told that there's `kNumFramesToStore` available.
128 EXPECT_EQ(kNumFramesToStore
,
129 __gwp_asan_get_deallocation_trace(&Meta
, &TraceOutput
, 1));