xref: /aosp_15_r20/external/gwp_asan/gwp_asan/tests/crash_handler_api.cpp (revision b302aa5039729da396909ef03e815160dab4448c)
1 //===-- crash_handler_api.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 "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"
13 
14 using Error = gwp_asan::Error;
15 using GuardedPoolAllocator = gwp_asan::GuardedPoolAllocator;
16 using AllocationMetadata = gwp_asan::AllocationMetadata;
17 using AllocatorState = gwp_asan::AllocatorState;
18 
19 class CrashHandlerAPITest : public ::testing::Test {
20 public:
SetUp()21   void SetUp() override { setupState(); }
22 
23 protected:
metadata(uintptr_t Addr,uintptr_t Size,bool IsDeallocated)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);
28 
29     size_t Slot = State.getNearestSlot(Addr);
30 
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]);
37 
38     return Slot;
39   }
40 
setupState()41   void setupState() {
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;
47   }
48 
setupBacktraces(AllocationMetadata * Meta)49   void setupBacktraces(AllocationMetadata *Meta) {
50     Meta->AllocationTrace.TraceSize = gwp_asan::compression::pack(
51         BacktraceConstants, kNumBacktraceConstants,
52         Meta->AllocationTrace.CompressedTrace,
53         AllocationMetadata::kStackFrameStorageBytes);
54 
55     if (Meta->IsDeallocated)
56       Meta->DeallocationTrace.TraceSize = gwp_asan::compression::pack(
57           BacktraceConstants, kNumBacktraceConstants,
58           Meta->DeallocationTrace.CompressedTrace,
59           AllocationMetadata::kStackFrameStorageBytes);
60   }
61 
checkBacktrace(const AllocationMetadata * Meta,bool IsDeallocated)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]);
69 
70     if (IsDeallocated) {
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]);
76     }
77   }
78 
checkMetadata(size_t Index,uintptr_t ErrorPtr)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));
88 
89     bool IsDeallocated = __gwp_asan_is_deallocated(Meta);
90     EXPECT_EQ(Metadata[Index].IsDeallocated, IsDeallocated);
91     checkBacktrace(Meta, IsDeallocated);
92 
93     if (!IsDeallocated)
94       return;
95 
96     EXPECT_EQ(Metadata[Index].DeallocationTrace.ThreadID,
97               __gwp_asan_get_deallocation_thread_id(Meta));
98   }
99 
100   static constexpr size_t kNumBacktraceConstants = 4;
101   static uintptr_t BacktraceConstants[kNumBacktraceConstants];
102   AllocatorState State = {};
103   AllocationMetadata Metadata[4] = {};
104   uintptr_t InternalFaultAddr;
105 };
106 
107 uintptr_t CrashHandlerAPITest::BacktraceConstants[kNumBacktraceConstants] = {
108     0xdeadbeef, 0xdeadc0de, 0xbadc0ffe, 0xcafef00d};
109 
TEST_F(CrashHandlerAPITest,PointerNotMine)110 TEST_F(CrashHandlerAPITest, PointerNotMine) {
111   uintptr_t UnknownPtr = reinterpret_cast<uintptr_t>(&State);
112 
113   EXPECT_FALSE(__gwp_asan_error_is_mine(&State, 0));
114   EXPECT_FALSE(__gwp_asan_error_is_mine(&State, UnknownPtr));
115 
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));
119 
120   EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, 0));
121   EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, UnknownPtr));
122 }
123 
TEST_F(CrashHandlerAPITest,PointerNotAllocated)124 TEST_F(CrashHandlerAPITest, PointerNotAllocated) {
125   uintptr_t FailureAddress = 0x9000;
126 
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));
132 }
133 
TEST_F(CrashHandlerAPITest,DoubleFree)134 TEST_F(CrashHandlerAPITest, DoubleFree) {
135   size_t Index =
136       metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true);
137   uintptr_t FailureAddress = 0x7000;
138 
139   State.FailureType = Error::DOUBLE_FREE;
140   State.FailureAddress = FailureAddress;
141 
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);
148 }
149 
TEST_F(CrashHandlerAPITest,InvalidFree)150 TEST_F(CrashHandlerAPITest, InvalidFree) {
151   size_t Index =
152       metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ false);
153   uintptr_t FailureAddress = 0x7001;
154 
155   State.FailureType = Error::INVALID_FREE;
156   State.FailureAddress = FailureAddress;
157 
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);
164 }
165 
TEST_F(CrashHandlerAPITest,InvalidFreeNoMetadata)166 TEST_F(CrashHandlerAPITest, InvalidFreeNoMetadata) {
167   uintptr_t FailureAddress = 0x7001;
168 
169   State.FailureType = Error::INVALID_FREE;
170   State.FailureAddress = FailureAddress;
171 
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));
178 }
179 
TEST_F(CrashHandlerAPITest,UseAfterFree)180 TEST_F(CrashHandlerAPITest, UseAfterFree) {
181   size_t Index =
182       metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true);
183   uintptr_t FailureAddress = 0x7001;
184 
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);
190 }
191 
TEST_F(CrashHandlerAPITest,BufferOverflow)192 TEST_F(CrashHandlerAPITest, BufferOverflow) {
193   size_t Index =
194       metadata(/* Addr */ 0x5f00, /* Size */ 0x100, /* IsDeallocated */ false);
195   uintptr_t FailureAddress = 0x6000;
196 
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);
202 }
203 
TEST_F(CrashHandlerAPITest,BufferUnderflow)204 TEST_F(CrashHandlerAPITest, BufferUnderflow) {
205   size_t Index =
206       metadata(/* Addr */ 0x3000, /* Size */ 0x10, /* IsDeallocated*/ false);
207   uintptr_t FailureAddress = 0x2fff;
208 
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);
214 }
215