125 lines · cpp
1//===-- dfsan_new_delete.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 DataflowSanitizer.10//11// Interceptors for operators new and delete.12//===----------------------------------------------------------------------===//13 14#include <stddef.h>15 16#include "dfsan.h"17#include "interception/interception.h"18#include "sanitizer_common/sanitizer_allocator.h"19#include "sanitizer_common/sanitizer_allocator_report.h"20 21using namespace __dfsan;22 23// Fake std::nothrow_t and std::align_val_t to avoid including <new>.24namespace std {25struct nothrow_t {};26enum class align_val_t : size_t {};27} // namespace std28 29// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.30#define OPERATOR_NEW_BODY(nothrow) \31 void *res = dfsan_malloc(size); \32 if (!nothrow && UNLIKELY(!res)) { \33 UNINITIALIZED BufferedStackTrace stack; \34 ReportOutOfMemory(size, &stack); \35 } \36 return res37#define OPERATOR_NEW_BODY_ALIGN(nothrow) \38 void *res = dfsan_memalign((uptr)align, size); \39 if (!nothrow && UNLIKELY(!res)) { \40 UNINITIALIZED BufferedStackTrace stack; \41 ReportOutOfMemory(size, &stack); \42 } \43 return res;44 45INTERCEPTOR_ATTRIBUTE46void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }47INTERCEPTOR_ATTRIBUTE48void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }49INTERCEPTOR_ATTRIBUTE50void *operator new(size_t size, std::nothrow_t const &) {51 OPERATOR_NEW_BODY(true /*nothrow*/);52}53INTERCEPTOR_ATTRIBUTE54void *operator new[](size_t size, std::nothrow_t const &) {55 OPERATOR_NEW_BODY(true /*nothrow*/);56}57INTERCEPTOR_ATTRIBUTE58void *operator new(size_t size, std::align_val_t align) {59 OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);60}61INTERCEPTOR_ATTRIBUTE62void *operator new[](size_t size, std::align_val_t align) {63 OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);64}65INTERCEPTOR_ATTRIBUTE66void *operator new(size_t size, std::align_val_t align,67 std::nothrow_t const &) {68 OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);69}70INTERCEPTOR_ATTRIBUTE71void *operator new[](size_t size, std::align_val_t align,72 std::nothrow_t const &) {73 OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);74}75 76#define OPERATOR_DELETE_BODY \77 if (ptr) \78 dfsan_deallocate(ptr)79 80INTERCEPTOR_ATTRIBUTE81void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY; }82INTERCEPTOR_ATTRIBUTE83void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }84INTERCEPTOR_ATTRIBUTE85void operator delete(void *ptr, std::nothrow_t const &) {86 OPERATOR_DELETE_BODY;87}88INTERCEPTOR_ATTRIBUTE89void operator delete[](void *ptr, std::nothrow_t const &) {90 OPERATOR_DELETE_BODY;91}92INTERCEPTOR_ATTRIBUTE93void operator delete(void *ptr, size_t size)NOEXCEPT { OPERATOR_DELETE_BODY; }94INTERCEPTOR_ATTRIBUTE95void operator delete[](void *ptr, size_t size) NOEXCEPT {96 OPERATOR_DELETE_BODY;97}98INTERCEPTOR_ATTRIBUTE99void operator delete(void *ptr, std::align_val_t align)NOEXCEPT {100 OPERATOR_DELETE_BODY;101}102INTERCEPTOR_ATTRIBUTE103void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {104 OPERATOR_DELETE_BODY;105}106INTERCEPTOR_ATTRIBUTE107void operator delete(void *ptr, std::align_val_t align,108 std::nothrow_t const &) {109 OPERATOR_DELETE_BODY;110}111INTERCEPTOR_ATTRIBUTE112void operator delete[](void *ptr, std::align_val_t align,113 std::nothrow_t const &) {114 OPERATOR_DELETE_BODY;115}116INTERCEPTOR_ATTRIBUTE117void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT {118 OPERATOR_DELETE_BODY;119}120INTERCEPTOR_ATTRIBUTE121void operator delete[](void *ptr, size_t size,122 std::align_val_t align) NOEXCEPT {123 OPERATOR_DELETE_BODY;124}125