brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · d7ed5b5 Raw
234 lines · cpp
1//===-- asan_interceptors.cpp ---------------------------------------------===//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// This file is a part of AddressSanitizer, an address sanity checker.10//11// Interceptors for operators new and delete.12//===----------------------------------------------------------------------===//13 14#include <stddef.h>15 16#include "asan_allocator.h"17#include "asan_internal.h"18#include "asan_report.h"19#include "asan_stack.h"20#include "interception/interception.h"21 22// C++ operators can't have dllexport attributes on Windows. We export them23// anyway by passing extra -export flags to the linker, which is exactly that24// dllexport would normally do. We need to export them in order to make the25// VS2015 dynamic CRT (MD) work.26#if SANITIZER_WINDOWS && defined(_MSC_VER)27#define CXX_OPERATOR_ATTRIBUTE28#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym))29#ifdef _WIN6430COMMENT_EXPORT("??2@YAPEAX_K@Z")                     // operator new31COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z")  // operator new nothrow32COMMENT_EXPORT("??3@YAXPEAX@Z")                      // operator delete33COMMENT_EXPORT("??3@YAXPEAX_K@Z")                    // sized operator delete34COMMENT_EXPORT("??_U@YAPEAX_K@Z")                    // operator new[]35COMMENT_EXPORT("??_V@YAXPEAX@Z")                     // operator delete[]36#else37COMMENT_EXPORT("??2@YAPAXI@Z")                    // operator new38COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z")  // operator new nothrow39COMMENT_EXPORT("??3@YAXPAX@Z")                    // operator delete40COMMENT_EXPORT("??3@YAXPAXI@Z")                   // sized operator delete41COMMENT_EXPORT("??_U@YAPAXI@Z")                   // operator new[]42COMMENT_EXPORT("??_V@YAXPAX@Z")                   // operator delete[]43#endif44#undef COMMENT_EXPORT45#else46#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE47#endif48 49using namespace __asan;50 51// This code has issues on OSX.52// See https://github.com/google/sanitizers/issues/131.53 54// Fake std::nothrow_t and std::align_val_t to avoid including <new>.55namespace std {56struct nothrow_t {};57enum class align_val_t: size_t {};58}  // namespace std59 60// TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM.61// For local pool allocation, align to SHADOW_GRANULARITY to match asan62// allocator behavior.63#define OPERATOR_NEW_BODY             \64  GET_STACK_TRACE_MALLOC;             \65  void *res = asan_new(size, &stack); \66  if (UNLIKELY(!res))                 \67    ReportOutOfMemory(size, &stack);  \68  return res69#define OPERATOR_NEW_BODY_NOTHROW \70  GET_STACK_TRACE_MALLOC;         \71  return asan_new(size, &stack)72#define OPERATOR_NEW_BODY_ARRAY             \73  GET_STACK_TRACE_MALLOC;                   \74  void *res = asan_new_array(size, &stack); \75  if (UNLIKELY(!res))                       \76    ReportOutOfMemory(size, &stack);        \77  return res78#define OPERATOR_NEW_BODY_ARRAY_NOTHROW \79  GET_STACK_TRACE_MALLOC;               \80  return asan_new_array(size, &stack)81#define OPERATOR_NEW_BODY_ALIGN                                         \82  GET_STACK_TRACE_MALLOC;                                               \83  void *res = asan_new_aligned(size, static_cast<uptr>(align), &stack); \84  if (UNLIKELY(!res))                                                   \85    ReportOutOfMemory(size, &stack);                                    \86  return res87#define OPERATOR_NEW_BODY_ALIGN_NOTHROW \88  GET_STACK_TRACE_MALLOC;               \89  return asan_new_aligned(size, static_cast<uptr>(align), &stack)90#define OPERATOR_NEW_BODY_ALIGN_ARRAY                                         \91  GET_STACK_TRACE_MALLOC;                                                     \92  void *res = asan_new_array_aligned(size, static_cast<uptr>(align), &stack); \93  if (UNLIKELY(!res))                                                         \94    ReportOutOfMemory(size, &stack);                                          \95  return res96#define OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW \97  GET_STACK_TRACE_MALLOC;                     \98  return asan_new_array_aligned(size, static_cast<uptr>(align), &stack)99 100// On OS X it's not enough to just provide our own 'operator new' and101// 'operator delete' implementations, because they're going to be in the102// runtime dylib, and the main executable will depend on both the runtime103// dylib and libstdc++, each of those'll have its implementation of new and104// delete.105// To make sure that C++ allocation/deallocation operators are overridden on106// OS X we need to intercept them using their mangled names.107#if !SANITIZER_APPLE108CXX_OPERATOR_ATTRIBUTE109void *operator new(size_t size) { OPERATOR_NEW_BODY; }110CXX_OPERATOR_ATTRIBUTE111void *operator new[](size_t size) { OPERATOR_NEW_BODY_ARRAY; }112CXX_OPERATOR_ATTRIBUTE113void *operator new(size_t size, std::nothrow_t const &) {114  OPERATOR_NEW_BODY_NOTHROW;115}116CXX_OPERATOR_ATTRIBUTE117void *operator new[](size_t size, std::nothrow_t const &) {118  OPERATOR_NEW_BODY_ARRAY_NOTHROW;119}120CXX_OPERATOR_ATTRIBUTE121void *operator new(size_t size, std::align_val_t align) {122  OPERATOR_NEW_BODY_ALIGN;123}124CXX_OPERATOR_ATTRIBUTE125void *operator new[](size_t size, std::align_val_t align) {126  OPERATOR_NEW_BODY_ALIGN_ARRAY;127}128CXX_OPERATOR_ATTRIBUTE129void *operator new(size_t size, std::align_val_t align,130                   std::nothrow_t const &) {131  OPERATOR_NEW_BODY_ALIGN_NOTHROW;132}133CXX_OPERATOR_ATTRIBUTE134void *operator new[](size_t size, std::align_val_t align,135                     std::nothrow_t const &) {136  OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW;137}138 139#else  // SANITIZER_APPLE140INTERCEPTOR(void *, _Znwm, size_t size) { OPERATOR_NEW_BODY; }141INTERCEPTOR(void *, _Znam, size_t size) { OPERATOR_NEW_BODY_ARRAY; }142INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {143  OPERATOR_NEW_BODY_NOTHROW;144}145INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {146  OPERATOR_NEW_BODY_ARRAY_NOTHROW;147}148#endif  // !SANITIZER_APPLE149 150#define OPERATOR_DELETE_BODY \151  GET_STACK_TRACE_FREE;      \152  asan_delete(ptr, &stack)153#define OPERATOR_DELETE_BODY_ARRAY \154  GET_STACK_TRACE_FREE;            \155  asan_delete_array(ptr, &stack)156#define OPERATOR_DELETE_BODY_ALIGN \157  GET_STACK_TRACE_FREE;            \158  asan_delete_aligned(ptr, static_cast<uptr>(align), &stack)159#define OPERATOR_DELETE_BODY_ALIGN_ARRAY \160  GET_STACK_TRACE_FREE;                  \161  asan_delete_array_aligned(ptr, static_cast<uptr>(align), &stack)162#define OPERATOR_DELETE_BODY_SIZE \163  GET_STACK_TRACE_FREE;           \164  asan_delete_sized(ptr, size, &stack)165#define OPERATOR_DELETE_BODY_SIZE_ARRAY \166  GET_STACK_TRACE_FREE;                 \167  asan_delete_array_sized(ptr, size, &stack)168#define OPERATOR_DELETE_BODY_SIZE_ALIGN \169  GET_STACK_TRACE_FREE;                 \170  asan_delete_sized_aligned(ptr, size, static_cast<uptr>(align), &stack)171#define OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY \172  GET_STACK_TRACE_FREE;                       \173  asan_delete_array_sized_aligned(ptr, size, static_cast<uptr>(align), &stack)174 175#if !SANITIZER_APPLE176CXX_OPERATOR_ATTRIBUTE177void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }178CXX_OPERATOR_ATTRIBUTE179void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY_ARRAY; }180CXX_OPERATOR_ATTRIBUTE181void operator delete(void *ptr, std::nothrow_t const &) {182  OPERATOR_DELETE_BODY;183}184CXX_OPERATOR_ATTRIBUTE185void operator delete[](void *ptr, std::nothrow_t const &) {186  OPERATOR_DELETE_BODY_ARRAY;187}188CXX_OPERATOR_ATTRIBUTE189void operator delete(void *ptr, size_t size) NOEXCEPT {190  OPERATOR_DELETE_BODY_SIZE;191}192CXX_OPERATOR_ATTRIBUTE193void operator delete[](void *ptr, size_t size) NOEXCEPT {194  OPERATOR_DELETE_BODY_SIZE_ARRAY;195}196CXX_OPERATOR_ATTRIBUTE197void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {198  OPERATOR_DELETE_BODY_ALIGN;199}200CXX_OPERATOR_ATTRIBUTE201void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {202  OPERATOR_DELETE_BODY_ALIGN_ARRAY;203}204CXX_OPERATOR_ATTRIBUTE205void operator delete(void *ptr, std::align_val_t align,206                     std::nothrow_t const &) {207  OPERATOR_DELETE_BODY_ALIGN;208}209CXX_OPERATOR_ATTRIBUTE210void operator delete[](void *ptr, std::align_val_t align,211                       std::nothrow_t const &) {212  OPERATOR_DELETE_BODY_ALIGN_ARRAY;213}214CXX_OPERATOR_ATTRIBUTE215void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT {216  OPERATOR_DELETE_BODY_SIZE_ALIGN;217}218CXX_OPERATOR_ATTRIBUTE219void operator delete[](void *ptr, size_t size,220                       std::align_val_t align) NOEXCEPT {221  OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY;222}223 224#else  // SANITIZER_APPLE225INTERCEPTOR(void, _ZdlPv, void *ptr) { OPERATOR_DELETE_BODY; }226INTERCEPTOR(void, _ZdaPv, void *ptr) { OPERATOR_DELETE_BODY_ARRAY; }227INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const &) {228  OPERATOR_DELETE_BODY;229}230INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const &) {231  OPERATOR_DELETE_BODY_ARRAY;232}233#endif  // !SANITIZER_APPLE234