brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · d270ed8 Raw
215 lines · cpp
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-exception6//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 14using Error = gwp_asan::Error;15using GuardedPoolAllocator = gwp_asan::GuardedPoolAllocator;16using AllocationMetadata = gwp_asan::AllocationMetadata;17using AllocatorState = gwp_asan::AllocatorState;18 19class CrashHandlerAPITest : public ::testing::Test {20public:21  void SetUp() override { setupState(); }22 23protected: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 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 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 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 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 107uintptr_t CrashHandlerAPITest::BacktraceConstants[kNumBacktraceConstants] = {108    0xdeadbeef, 0xdeadc0de, 0xbadc0ffe, 0xcafef00d};109 110TEST_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 124TEST_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 134TEST_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 150TEST_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 166TEST_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 180TEST_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 192TEST_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 204TEST_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