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
16TEST_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 EXPECT_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
40TEST_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 EXPECT_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
71TEST(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;
77 return 2u;
78 });
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);
83}
84
85TEST(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));
91
92 // Indicate that there were more frames, and we just didn't have enough
93 // room to store them.
94 return Size * 2;
95 });
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));
100}
101
102TEST(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;
110 });
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));
115}
116
117TEST(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;
125 });
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));
130}
131

source code of compiler-rt/lib/gwp_asan/tests/backtrace.cpp