xref: /llvm-project/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp (revision b27f657f89c605f635f79ebcbacd8a729f8e1bff)
1a6258684SMitch Phillips //===-- crash_handler_api.cpp -----------------------------------*- C++ -*-===//
2a6258684SMitch Phillips //
3a6258684SMitch Phillips // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a6258684SMitch Phillips // See https://llvm.org/LICENSE.txt for license information.
5a6258684SMitch Phillips // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a6258684SMitch Phillips //
7a6258684SMitch Phillips //===----------------------------------------------------------------------===//
8a6258684SMitch Phillips 
9a6258684SMitch Phillips #include "gwp_asan/crash_handler.h"
10a6258684SMitch Phillips #include "gwp_asan/guarded_pool_allocator.h"
11a6258684SMitch Phillips #include "gwp_asan/stack_trace_compressor.h"
12a6258684SMitch Phillips #include "gwp_asan/tests/harness.h"
13a6258684SMitch Phillips 
14a6258684SMitch Phillips using Error = gwp_asan::Error;
15a6258684SMitch Phillips using GuardedPoolAllocator = gwp_asan::GuardedPoolAllocator;
16a6258684SMitch Phillips using AllocationMetadata = gwp_asan::AllocationMetadata;
17a6258684SMitch Phillips using AllocatorState = gwp_asan::AllocatorState;
18a6258684SMitch Phillips 
19*b27f657fSAlex Brachet class CrashHandlerAPITest : public ::testing::Test {
20a6258684SMitch Phillips public:
SetUp()21a6258684SMitch Phillips   void SetUp() override { setupState(); }
22a6258684SMitch Phillips 
23a6258684SMitch Phillips protected:
metadata(uintptr_t Addr,uintptr_t Size,bool IsDeallocated)24a6258684SMitch Phillips   size_t metadata(uintptr_t Addr, uintptr_t Size, bool IsDeallocated) {
25a6258684SMitch Phillips     // Should only be allocating the 0x3000, 0x5000, 0x7000, 0x9000 pages.
26a6258684SMitch Phillips     EXPECT_GE(Addr, 0x3000u);
27a6258684SMitch Phillips     EXPECT_LT(Addr, 0xa000u);
28a6258684SMitch Phillips 
29a6258684SMitch Phillips     size_t Slot = State.getNearestSlot(Addr);
30a6258684SMitch Phillips 
31a6258684SMitch Phillips     Metadata[Slot].Addr = Addr;
323d8823b8SMitch Phillips     Metadata[Slot].RequestedSize = Size;
33a6258684SMitch Phillips     Metadata[Slot].IsDeallocated = IsDeallocated;
34a6258684SMitch Phillips     Metadata[Slot].AllocationTrace.ThreadID = 123;
35a6258684SMitch Phillips     Metadata[Slot].DeallocationTrace.ThreadID = 321;
36a6258684SMitch Phillips     setupBacktraces(&Metadata[Slot]);
37a6258684SMitch Phillips 
38a6258684SMitch Phillips     return Slot;
39a6258684SMitch Phillips   }
40a6258684SMitch Phillips 
setupState()41a6258684SMitch Phillips   void setupState() {
42a6258684SMitch Phillips     State.GuardedPagePool = 0x2000;
4335b5499dSMitch Phillips     State.GuardedPagePoolEnd = 0xc000;
4435b5499dSMitch Phillips     InternalFaultAddr = State.GuardedPagePoolEnd - 0x10;
45a6258684SMitch Phillips     State.MaxSimultaneousAllocations = 4; // 0x3000, 0x5000, 0x7000, 0x9000.
46a6258684SMitch Phillips     State.PageSize = 0x1000;
47a6258684SMitch Phillips   }
48a6258684SMitch Phillips 
setupBacktraces(AllocationMetadata * Meta)49a6258684SMitch Phillips   void setupBacktraces(AllocationMetadata *Meta) {
50a6258684SMitch Phillips     Meta->AllocationTrace.TraceSize = gwp_asan::compression::pack(
51a6258684SMitch Phillips         BacktraceConstants, kNumBacktraceConstants,
52a6258684SMitch Phillips         Meta->AllocationTrace.CompressedTrace,
53a6258684SMitch Phillips         AllocationMetadata::kStackFrameStorageBytes);
54a6258684SMitch Phillips 
55a6258684SMitch Phillips     if (Meta->IsDeallocated)
56a6258684SMitch Phillips       Meta->DeallocationTrace.TraceSize = gwp_asan::compression::pack(
57a6258684SMitch Phillips           BacktraceConstants, kNumBacktraceConstants,
58a6258684SMitch Phillips           Meta->DeallocationTrace.CompressedTrace,
59a6258684SMitch Phillips           AllocationMetadata::kStackFrameStorageBytes);
60a6258684SMitch Phillips   }
61a6258684SMitch Phillips 
checkBacktrace(const AllocationMetadata * Meta,bool IsDeallocated)62a6258684SMitch Phillips   void checkBacktrace(const AllocationMetadata *Meta, bool IsDeallocated) {
63a6258684SMitch Phillips     uintptr_t Buffer[kNumBacktraceConstants];
64a6258684SMitch Phillips     size_t NumBacktraceConstants = kNumBacktraceConstants;
650bfc4890SMitch Phillips     EXPECT_EQ(NumBacktraceConstants, __gwp_asan_get_allocation_trace(
660bfc4890SMitch Phillips                                          Meta, Buffer, kNumBacktraceConstants));
67a6258684SMitch Phillips     for (size_t i = 0; i < kNumBacktraceConstants; ++i)
68a6258684SMitch Phillips       EXPECT_EQ(Buffer[i], BacktraceConstants[i]);
69a6258684SMitch Phillips 
70a6258684SMitch Phillips     if (IsDeallocated) {
71a6258684SMitch Phillips       EXPECT_EQ(NumBacktraceConstants,
720bfc4890SMitch Phillips                 __gwp_asan_get_deallocation_trace(Meta, Buffer,
73a6258684SMitch Phillips                                                   kNumBacktraceConstants));
74a6258684SMitch Phillips       for (size_t i = 0; i < kNumBacktraceConstants; ++i)
75a6258684SMitch Phillips         EXPECT_EQ(Buffer[i], BacktraceConstants[i]);
76a6258684SMitch Phillips     }
77a6258684SMitch Phillips   }
78a6258684SMitch Phillips 
checkMetadata(size_t Index,uintptr_t ErrorPtr)79a6258684SMitch Phillips   void checkMetadata(size_t Index, uintptr_t ErrorPtr) {
80a6258684SMitch Phillips     const AllocationMetadata *Meta =
81a6258684SMitch Phillips         __gwp_asan_get_metadata(&State, Metadata, ErrorPtr);
82a6258684SMitch Phillips     EXPECT_NE(nullptr, Meta);
830bfc4890SMitch Phillips     EXPECT_EQ(Metadata[Index].Addr, __gwp_asan_get_allocation_address(Meta));
843d8823b8SMitch Phillips     EXPECT_EQ(Metadata[Index].RequestedSize,
853d8823b8SMitch Phillips               __gwp_asan_get_allocation_size(Meta));
86a6258684SMitch Phillips     EXPECT_EQ(Metadata[Index].AllocationTrace.ThreadID,
870bfc4890SMitch Phillips               __gwp_asan_get_allocation_thread_id(Meta));
88a6258684SMitch Phillips 
890bfc4890SMitch Phillips     bool IsDeallocated = __gwp_asan_is_deallocated(Meta);
90a6258684SMitch Phillips     EXPECT_EQ(Metadata[Index].IsDeallocated, IsDeallocated);
91a6258684SMitch Phillips     checkBacktrace(Meta, IsDeallocated);
92a6258684SMitch Phillips 
93a6258684SMitch Phillips     if (!IsDeallocated)
94a6258684SMitch Phillips       return;
95a6258684SMitch Phillips 
96a6258684SMitch Phillips     EXPECT_EQ(Metadata[Index].DeallocationTrace.ThreadID,
970bfc4890SMitch Phillips               __gwp_asan_get_deallocation_thread_id(Meta));
98a6258684SMitch Phillips   }
99a6258684SMitch Phillips 
100a6258684SMitch Phillips   static constexpr size_t kNumBacktraceConstants = 4;
101a6258684SMitch Phillips   static uintptr_t BacktraceConstants[kNumBacktraceConstants];
102a6258684SMitch Phillips   AllocatorState State = {};
103a6258684SMitch Phillips   AllocationMetadata Metadata[4] = {};
10435b5499dSMitch Phillips   uintptr_t InternalFaultAddr;
105a6258684SMitch Phillips };
106a6258684SMitch Phillips 
107a6258684SMitch Phillips uintptr_t CrashHandlerAPITest::BacktraceConstants[kNumBacktraceConstants] = {
1080c3b2986SMitch Phillips     0xdeadbeef, 0xdeadc0de, 0xbadc0ffe, 0xcafef00d};
109a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,PointerNotMine)110a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, PointerNotMine) {
111a6258684SMitch Phillips   uintptr_t UnknownPtr = reinterpret_cast<uintptr_t>(&State);
112a6258684SMitch Phillips 
113a6258684SMitch Phillips   EXPECT_FALSE(__gwp_asan_error_is_mine(&State, 0));
114a6258684SMitch Phillips   EXPECT_FALSE(__gwp_asan_error_is_mine(&State, UnknownPtr));
115a6258684SMitch Phillips 
116a6258684SMitch Phillips   EXPECT_EQ(Error::UNKNOWN, __gwp_asan_diagnose_error(&State, Metadata, 0));
117a6258684SMitch Phillips   EXPECT_EQ(Error::UNKNOWN,
118a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, UnknownPtr));
119a6258684SMitch Phillips 
120a6258684SMitch Phillips   EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, 0));
121a6258684SMitch Phillips   EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, UnknownPtr));
122a6258684SMitch Phillips }
123a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,PointerNotAllocated)124a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, PointerNotAllocated) {
125a6258684SMitch Phillips   uintptr_t FailureAddress = 0x9000;
126a6258684SMitch Phillips 
127a6258684SMitch Phillips   EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress));
128a6258684SMitch Phillips   EXPECT_EQ(Error::UNKNOWN,
129a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, FailureAddress));
13035b5499dSMitch Phillips   EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress));
131a6258684SMitch Phillips   EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, FailureAddress));
132a6258684SMitch Phillips }
133a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,DoubleFree)134a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, DoubleFree) {
135a6258684SMitch Phillips   size_t Index =
136a6258684SMitch Phillips       metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true);
137a6258684SMitch Phillips   uintptr_t FailureAddress = 0x7000;
138a6258684SMitch Phillips 
139a6258684SMitch Phillips   State.FailureType = Error::DOUBLE_FREE;
140a6258684SMitch Phillips   State.FailureAddress = FailureAddress;
141a6258684SMitch Phillips 
142a6258684SMitch Phillips   EXPECT_TRUE(__gwp_asan_error_is_mine(&State));
143a6258684SMitch Phillips   EXPECT_EQ(Error::DOUBLE_FREE,
144a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, 0x0));
14535b5499dSMitch Phillips   EXPECT_EQ(FailureAddress,
14635b5499dSMitch Phillips             __gwp_asan_get_internal_crash_address(&State, InternalFaultAddr));
147a6258684SMitch Phillips   checkMetadata(Index, FailureAddress);
148a6258684SMitch Phillips }
149a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,InvalidFree)150a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, InvalidFree) {
151a6258684SMitch Phillips   size_t Index =
152a6258684SMitch Phillips       metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ false);
153a6258684SMitch Phillips   uintptr_t FailureAddress = 0x7001;
154a6258684SMitch Phillips 
155a6258684SMitch Phillips   State.FailureType = Error::INVALID_FREE;
156a6258684SMitch Phillips   State.FailureAddress = FailureAddress;
157a6258684SMitch Phillips 
158a6258684SMitch Phillips   EXPECT_TRUE(__gwp_asan_error_is_mine(&State));
159a6258684SMitch Phillips   EXPECT_EQ(Error::INVALID_FREE,
160a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, 0x0));
16135b5499dSMitch Phillips   EXPECT_EQ(FailureAddress,
16235b5499dSMitch Phillips             __gwp_asan_get_internal_crash_address(&State, InternalFaultAddr));
163a6258684SMitch Phillips   checkMetadata(Index, FailureAddress);
164a6258684SMitch Phillips }
165a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,InvalidFreeNoMetadata)166a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, InvalidFreeNoMetadata) {
167a6258684SMitch Phillips   uintptr_t FailureAddress = 0x7001;
168a6258684SMitch Phillips 
169a6258684SMitch Phillips   State.FailureType = Error::INVALID_FREE;
170a6258684SMitch Phillips   State.FailureAddress = FailureAddress;
171a6258684SMitch Phillips 
172a6258684SMitch Phillips   EXPECT_TRUE(__gwp_asan_error_is_mine(&State));
173a6258684SMitch Phillips   EXPECT_EQ(Error::INVALID_FREE,
174a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, 0x0));
17535b5499dSMitch Phillips   EXPECT_EQ(FailureAddress,
17635b5499dSMitch Phillips             __gwp_asan_get_internal_crash_address(&State, InternalFaultAddr));
177a6258684SMitch Phillips   EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, FailureAddress));
178a6258684SMitch Phillips }
179a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,UseAfterFree)180a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, UseAfterFree) {
181a6258684SMitch Phillips   size_t Index =
182a6258684SMitch Phillips       metadata(/* Addr */ 0x7000, /* Size */ 0x20, /* IsDeallocated */ true);
183a6258684SMitch Phillips   uintptr_t FailureAddress = 0x7001;
184a6258684SMitch Phillips 
185a6258684SMitch Phillips   EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress));
186a6258684SMitch Phillips   EXPECT_EQ(Error::USE_AFTER_FREE,
187a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, FailureAddress));
18835b5499dSMitch Phillips   EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress));
189a6258684SMitch Phillips   checkMetadata(Index, FailureAddress);
190a6258684SMitch Phillips }
191a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,BufferOverflow)192a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, BufferOverflow) {
193a6258684SMitch Phillips   size_t Index =
194a6258684SMitch Phillips       metadata(/* Addr */ 0x5f00, /* Size */ 0x100, /* IsDeallocated */ false);
195a6258684SMitch Phillips   uintptr_t FailureAddress = 0x6000;
196a6258684SMitch Phillips 
197a6258684SMitch Phillips   EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress));
198a6258684SMitch Phillips   EXPECT_EQ(Error::BUFFER_OVERFLOW,
199a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, FailureAddress));
20035b5499dSMitch Phillips   EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress));
201a6258684SMitch Phillips   checkMetadata(Index, FailureAddress);
202a6258684SMitch Phillips }
203a6258684SMitch Phillips 
TEST_F(CrashHandlerAPITest,BufferUnderflow)204a6258684SMitch Phillips TEST_F(CrashHandlerAPITest, BufferUnderflow) {
205a6258684SMitch Phillips   size_t Index =
206a6258684SMitch Phillips       metadata(/* Addr */ 0x3000, /* Size */ 0x10, /* IsDeallocated*/ false);
207a6258684SMitch Phillips   uintptr_t FailureAddress = 0x2fff;
208a6258684SMitch Phillips 
209a6258684SMitch Phillips   EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress));
210a6258684SMitch Phillips   EXPECT_EQ(Error::BUFFER_UNDERFLOW,
211a6258684SMitch Phillips             __gwp_asan_diagnose_error(&State, Metadata, FailureAddress));
21235b5499dSMitch Phillips   EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress));
213a6258684SMitch Phillips   checkMetadata(Index, FailureAddress);
214a6258684SMitch Phillips }
215