1 //===-- crash_handler_api.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 //===----------------------------------------------------------------------===//
9 #include "gwp_asan/crash_handler.h"
10 #include "gwp_asan/guarded_pool_allocator.h"
11 #include "gwp_asan/stack_trace_compressor.h"
12 #include "gwp_asan/tests/harness.h"
14 using Error
= gwp_asan::Error
;
15 using GuardedPoolAllocator
= gwp_asan::GuardedPoolAllocator
;
16 using AllocationMetadata
= gwp_asan::AllocationMetadata
;
17 using AllocatorState
= gwp_asan::AllocatorState
;
19 class CrashHandlerAPITest
: public ::testing::Test
{
21 void SetUp() override
{ setupState(); }
24 size_t metadata(uintptr_t Addr
, uintptr_t Size
, bool IsDeallocated
) {
25 // Should only be allocating the 0x3000, 0x5000, 0x7000, 0x9000 pages.
26 EXPECT_GE(Addr
, 0x3000u
);
27 EXPECT_LT(Addr
, 0xa000u
);
29 size_t Slot
= State
.getNearestSlot(Addr
);
31 Metadata
[Slot
].Addr
= Addr
;
32 Metadata
[Slot
].RequestedSize
= Size
;
33 Metadata
[Slot
].IsDeallocated
= IsDeallocated
;
34 Metadata
[Slot
].AllocationTrace
.ThreadID
= 123;
35 Metadata
[Slot
].DeallocationTrace
.ThreadID
= 321;
36 setupBacktraces(&Metadata
[Slot
]);
42 State
.GuardedPagePool
= 0x2000;
43 State
.GuardedPagePoolEnd
= 0xc000;
44 InternalFaultAddr
= State
.GuardedPagePoolEnd
- 0x10;
45 State
.MaxSimultaneousAllocations
= 4; // 0x3000, 0x5000, 0x7000, 0x9000.
46 State
.PageSize
= 0x1000;
49 void setupBacktraces(AllocationMetadata
*Meta
) {
50 Meta
->AllocationTrace
.TraceSize
= gwp_asan::compression::pack(
51 BacktraceConstants
, kNumBacktraceConstants
,
52 Meta
->AllocationTrace
.CompressedTrace
,
53 AllocationMetadata::kStackFrameStorageBytes
);
55 if (Meta
->IsDeallocated
)
56 Meta
->DeallocationTrace
.TraceSize
= gwp_asan::compression::pack(
57 BacktraceConstants
, kNumBacktraceConstants
,
58 Meta
->DeallocationTrace
.CompressedTrace
,
59 AllocationMetadata::kStackFrameStorageBytes
);
62 void checkBacktrace(const AllocationMetadata
*Meta
, bool IsDeallocated
) {
63 uintptr_t Buffer
[kNumBacktraceConstants
];
64 size_t NumBacktraceConstants
= kNumBacktraceConstants
;
65 EXPECT_EQ(NumBacktraceConstants
, __gwp_asan_get_allocation_trace(
66 Meta
, Buffer
, kNumBacktraceConstants
));
67 for (size_t i
= 0; i
< kNumBacktraceConstants
; ++i
)
68 EXPECT_EQ(Buffer
[i
], BacktraceConstants
[i
]);
71 EXPECT_EQ(NumBacktraceConstants
,
72 __gwp_asan_get_deallocation_trace(Meta
, Buffer
,
73 kNumBacktraceConstants
));
74 for (size_t i
= 0; i
< kNumBacktraceConstants
; ++i
)
75 EXPECT_EQ(Buffer
[i
], BacktraceConstants
[i
]);
79 void checkMetadata(size_t Index
, uintptr_t ErrorPtr
) {
80 const AllocationMetadata
*Meta
=
81 __gwp_asan_get_metadata(&State
, Metadata
, ErrorPtr
);
82 EXPECT_NE(nullptr, Meta
);
83 EXPECT_EQ(Metadata
[Index
].Addr
, __gwp_asan_get_allocation_address(Meta
));
84 EXPECT_EQ(Metadata
[Index
].RequestedSize
,
85 __gwp_asan_get_allocation_size(Meta
));
86 EXPECT_EQ(Metadata
[Index
].AllocationTrace
.ThreadID
,
87 __gwp_asan_get_allocation_thread_id(Meta
));
89 bool IsDeallocated
= __gwp_asan_is_deallocated(Meta
);
90 EXPECT_EQ(Metadata
[Index
].IsDeallocated
, IsDeallocated
);
91 checkBacktrace(Meta
, IsDeallocated
);
96 EXPECT_EQ(Metadata
[Index
].DeallocationTrace
.ThreadID
,
97 __gwp_asan_get_deallocation_thread_id(Meta
));
100 static constexpr size_t kNumBacktraceConstants
= 4;
101 static uintptr_t BacktraceConstants
[kNumBacktraceConstants
];
102 AllocatorState State
= {};
103 AllocationMetadata Metadata
[4] = {};
104 uintptr_t InternalFaultAddr
;
107 uintptr_t CrashHandlerAPITest::BacktraceConstants
[kNumBacktraceConstants
] = {
108 0xdeadbeef, 0xdeadc0de, 0xbadc0ffe, 0xcafef00d};
110 TEST_F(CrashHandlerAPITest
, PointerNotMine
) {
111 uintptr_t UnknownPtr
= reinterpret_cast<uintptr_t>(&State
);
113 EXPECT_FALSE(__gwp_asan_error_is_mine(&State
, 0));
114 EXPECT_FALSE(__gwp_asan_error_is_mine(&State
, UnknownPtr
));
116 EXPECT_EQ(Error::UNKNOWN
, __gwp_asan_diagnose_error(&State
, Metadata
, 0));
117 EXPECT_EQ(Error::UNKNOWN
,
118 __gwp_asan_diagnose_error(&State
, Metadata
, UnknownPtr
));
120 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State
, Metadata
, 0));
121 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State
, Metadata
, UnknownPtr
));
124 TEST_F(CrashHandlerAPITest
, PointerNotAllocated
) {
125 uintptr_t FailureAddress
= 0x9000;
127 EXPECT_TRUE(__gwp_asan_error_is_mine(&State
, FailureAddress
));
128 EXPECT_EQ(Error::UNKNOWN
,
129 __gwp_asan_diagnose_error(&State
, Metadata
, FailureAddress
));
130 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State
, FailureAddress
));
131 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State
, Metadata
, FailureAddress
));
134 TEST_F(CrashHandlerAPITest
, DoubleFree
) {
136 metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true);
137 uintptr_t FailureAddress
= 0x7000;
139 State
.FailureType
= Error::DOUBLE_FREE
;
140 State
.FailureAddress
= FailureAddress
;
142 EXPECT_TRUE(__gwp_asan_error_is_mine(&State
));
143 EXPECT_EQ(Error::DOUBLE_FREE
,
144 __gwp_asan_diagnose_error(&State
, Metadata
, 0x0));
145 EXPECT_EQ(FailureAddress
,
146 __gwp_asan_get_internal_crash_address(&State
, InternalFaultAddr
));
147 checkMetadata(Index
, FailureAddress
);
150 TEST_F(CrashHandlerAPITest
, InvalidFree
) {
152 metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ false);
153 uintptr_t FailureAddress
= 0x7001;
155 State
.FailureType
= Error::INVALID_FREE
;
156 State
.FailureAddress
= FailureAddress
;
158 EXPECT_TRUE(__gwp_asan_error_is_mine(&State
));
159 EXPECT_EQ(Error::INVALID_FREE
,
160 __gwp_asan_diagnose_error(&State
, Metadata
, 0x0));
161 EXPECT_EQ(FailureAddress
,
162 __gwp_asan_get_internal_crash_address(&State
, InternalFaultAddr
));
163 checkMetadata(Index
, FailureAddress
);
166 TEST_F(CrashHandlerAPITest
, InvalidFreeNoMetadata
) {
167 uintptr_t FailureAddress
= 0x7001;
169 State
.FailureType
= Error::INVALID_FREE
;
170 State
.FailureAddress
= FailureAddress
;
172 EXPECT_TRUE(__gwp_asan_error_is_mine(&State
));
173 EXPECT_EQ(Error::INVALID_FREE
,
174 __gwp_asan_diagnose_error(&State
, Metadata
, 0x0));
175 EXPECT_EQ(FailureAddress
,
176 __gwp_asan_get_internal_crash_address(&State
, InternalFaultAddr
));
177 EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State
, Metadata
, FailureAddress
));
180 TEST_F(CrashHandlerAPITest
, UseAfterFree
) {
182 metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true);
183 uintptr_t FailureAddress
= 0x7001;
185 EXPECT_TRUE(__gwp_asan_error_is_mine(&State
, FailureAddress
));
186 EXPECT_EQ(Error::USE_AFTER_FREE
,
187 __gwp_asan_diagnose_error(&State
, Metadata
, FailureAddress
));
188 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State
, FailureAddress
));
189 checkMetadata(Index
, FailureAddress
);
192 TEST_F(CrashHandlerAPITest
, BufferOverflow
) {
194 metadata(/* Addr */ 0x5f00, /* Size */ 0x100, /* IsDeallocated */ false);
195 uintptr_t FailureAddress
= 0x6000;
197 EXPECT_TRUE(__gwp_asan_error_is_mine(&State
, FailureAddress
));
198 EXPECT_EQ(Error::BUFFER_OVERFLOW
,
199 __gwp_asan_diagnose_error(&State
, Metadata
, FailureAddress
));
200 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State
, FailureAddress
));
201 checkMetadata(Index
, FailureAddress
);
204 TEST_F(CrashHandlerAPITest
, BufferUnderflow
) {
206 metadata(/* Addr */ 0x3000, /* Size */ 0x10, /* IsDeallocated*/ false);
207 uintptr_t FailureAddress
= 0x2fff;
209 EXPECT_TRUE(__gwp_asan_error_is_mine(&State
, FailureAddress
));
210 EXPECT_EQ(Error::BUFFER_UNDERFLOW
,
211 __gwp_asan_diagnose_error(&State
, Metadata
, FailureAddress
));
212 EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State
, FailureAddress
));
213 checkMetadata(Index
, FailureAddress
);