Path: blob/main/contrib/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp
35233 views
//===-- asan_interceptors.cpp ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of AddressSanitizer, an address sanity checker.9//10// Interceptors for operators new and delete.11//===----------------------------------------------------------------------===//1213#include <stddef.h>1415#include "asan_allocator.h"16#include "asan_internal.h"17#include "asan_report.h"18#include "asan_stack.h"19#include "interception/interception.h"2021// C++ operators can't have dllexport attributes on Windows. We export them22// anyway by passing extra -export flags to the linker, which is exactly that23// dllexport would normally do. We need to export them in order to make the24// VS2015 dynamic CRT (MD) work.25#if SANITIZER_WINDOWS && defined(_MSC_VER)26#define CXX_OPERATOR_ATTRIBUTE27#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym))28#ifdef _WIN6429COMMENT_EXPORT("??2@YAPEAX_K@Z") // operator new30COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") // operator new nothrow31COMMENT_EXPORT("??3@YAXPEAX@Z") // operator delete32COMMENT_EXPORT("??3@YAXPEAX_K@Z") // sized operator delete33COMMENT_EXPORT("??_U@YAPEAX_K@Z") // operator new[]34COMMENT_EXPORT("??_V@YAXPEAX@Z") // operator delete[]35#else36COMMENT_EXPORT("??2@YAPAXI@Z") // operator new37COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z") // operator new nothrow38COMMENT_EXPORT("??3@YAXPAX@Z") // operator delete39COMMENT_EXPORT("??3@YAXPAXI@Z") // sized operator delete40COMMENT_EXPORT("??_U@YAPAXI@Z") // operator new[]41COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[]42#endif43#undef COMMENT_EXPORT44#else45#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE46#endif4748using namespace __asan;4950// This code has issues on OSX.51// See https://github.com/google/sanitizers/issues/131.5253// Fake std::nothrow_t and std::align_val_t to avoid including <new>.54namespace std {55struct nothrow_t {};56enum class align_val_t: size_t {};57} // namespace std5859// TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM.60// For local pool allocation, align to SHADOW_GRANULARITY to match asan61// allocator behavior.62#define OPERATOR_NEW_BODY(type, nothrow) \63GET_STACK_TRACE_MALLOC; \64void *res = asan_memalign(0, size, &stack, type); \65if (!nothrow && UNLIKELY(!res)) \66ReportOutOfMemory(size, &stack); \67return res;68#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \69GET_STACK_TRACE_MALLOC; \70void *res = asan_memalign((uptr)align, size, &stack, type); \71if (!nothrow && UNLIKELY(!res)) \72ReportOutOfMemory(size, &stack); \73return res;7475// On OS X it's not enough to just provide our own 'operator new' and76// 'operator delete' implementations, because they're going to be in the77// runtime dylib, and the main executable will depend on both the runtime78// dylib and libstdc++, each of those'll have its implementation of new and79// delete.80// To make sure that C++ allocation/deallocation operators are overridden on81// OS X we need to intercept them using their mangled names.82#if !SANITIZER_APPLE83CXX_OPERATOR_ATTRIBUTE84void *operator new(size_t size)85{ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); }86CXX_OPERATOR_ATTRIBUTE87void *operator new[](size_t size)88{ OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); }89CXX_OPERATOR_ATTRIBUTE90void *operator new(size_t size, std::nothrow_t const&)91{ OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); }92CXX_OPERATOR_ATTRIBUTE93void *operator new[](size_t size, std::nothrow_t const&)94{ OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); }95CXX_OPERATOR_ATTRIBUTE96void *operator new(size_t size, std::align_val_t align)97{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); }98CXX_OPERATOR_ATTRIBUTE99void *operator new[](size_t size, std::align_val_t align)100{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); }101CXX_OPERATOR_ATTRIBUTE102void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)103{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/); }104CXX_OPERATOR_ATTRIBUTE105void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)106{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); }107108#else // SANITIZER_APPLE109INTERCEPTOR(void *, _Znwm, size_t size) {110OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);111}112INTERCEPTOR(void *, _Znam, size_t size) {113OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);114}115INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {116OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);117}118INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {119OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);120}121#endif // !SANITIZER_APPLE122123#define OPERATOR_DELETE_BODY(type) \124GET_STACK_TRACE_FREE; \125asan_delete(ptr, 0, 0, &stack, type);126127#define OPERATOR_DELETE_BODY_SIZE(type) \128GET_STACK_TRACE_FREE; \129asan_delete(ptr, size, 0, &stack, type);130131#define OPERATOR_DELETE_BODY_ALIGN(type) \132GET_STACK_TRACE_FREE; \133asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type);134135#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \136GET_STACK_TRACE_FREE; \137asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);138139#if !SANITIZER_APPLE140CXX_OPERATOR_ATTRIBUTE141void operator delete(void *ptr) NOEXCEPT142{ OPERATOR_DELETE_BODY(FROM_NEW); }143CXX_OPERATOR_ATTRIBUTE144void operator delete[](void *ptr) NOEXCEPT145{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }146CXX_OPERATOR_ATTRIBUTE147void operator delete(void *ptr, std::nothrow_t const&)148{ OPERATOR_DELETE_BODY(FROM_NEW); }149CXX_OPERATOR_ATTRIBUTE150void operator delete[](void *ptr, std::nothrow_t const&)151{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }152CXX_OPERATOR_ATTRIBUTE153void operator delete(void *ptr, size_t size) NOEXCEPT154{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW); }155CXX_OPERATOR_ATTRIBUTE156void operator delete[](void *ptr, size_t size) NOEXCEPT157{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR); }158CXX_OPERATOR_ATTRIBUTE159void operator delete(void *ptr, std::align_val_t align) NOEXCEPT160{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); }161CXX_OPERATOR_ATTRIBUTE162void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT163{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); }164CXX_OPERATOR_ATTRIBUTE165void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)166{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); }167CXX_OPERATOR_ATTRIBUTE168void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)169{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); }170CXX_OPERATOR_ATTRIBUTE171void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT172{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW); }173CXX_OPERATOR_ATTRIBUTE174void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT175{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); }176177#else // SANITIZER_APPLE178INTERCEPTOR(void, _ZdlPv, void *ptr)179{ OPERATOR_DELETE_BODY(FROM_NEW); }180INTERCEPTOR(void, _ZdaPv, void *ptr)181{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }182INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)183{ OPERATOR_DELETE_BODY(FROM_NEW); }184INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)185{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }186#endif // !SANITIZER_APPLE187188189