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