1353944Sdim//===-- msan_new_delete.cpp -----------------------------------------------===//
2353944Sdim//
3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353944Sdim// See https://llvm.org/LICENSE.txt for license information.
5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353944Sdim//
7353944Sdim//===----------------------------------------------------------------------===//
8353944Sdim//
9353944Sdim// This file is a part of MemorySanitizer.
10353944Sdim//
11353944Sdim// Interceptors for operators new and delete.
12353944Sdim//===----------------------------------------------------------------------===//
13353944Sdim
14353944Sdim#include "msan.h"
15353944Sdim#include "interception/interception.h"
16353944Sdim#include "sanitizer_common/sanitizer_allocator.h"
17353944Sdim#include "sanitizer_common/sanitizer_allocator_report.h"
18353944Sdim
19353944Sdim#if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
20353944Sdim
21353944Sdim#include <stddef.h>
22353944Sdim
23353944Sdimusing namespace __msan;
24353944Sdim
25353944Sdim// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
26353944Sdimnamespace std {
27353944Sdim  struct nothrow_t {};
28353944Sdim  enum class align_val_t: size_t {};
29353944Sdim}  // namespace std
30353944Sdim
31353944Sdim
32353944Sdim// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
33353944Sdim#define OPERATOR_NEW_BODY(nothrow) \
34353944Sdim  GET_MALLOC_STACK_TRACE; \
35353944Sdim  void *res = msan_malloc(size, &stack);\
36353944Sdim  if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
37353944Sdim  return res
38353944Sdim#define OPERATOR_NEW_BODY_ALIGN(nothrow) \
39353944Sdim  GET_MALLOC_STACK_TRACE;\
40353944Sdim  void *res = msan_memalign((uptr)align, size, &stack);\
41353944Sdim  if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
42353944Sdim  return res;
43353944Sdim
44353944SdimINTERCEPTOR_ATTRIBUTE
45353944Sdimvoid *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
46353944SdimINTERCEPTOR_ATTRIBUTE
47353944Sdimvoid *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
48353944SdimINTERCEPTOR_ATTRIBUTE
49353944Sdimvoid *operator new(size_t size, std::nothrow_t const&) {
50353944Sdim  OPERATOR_NEW_BODY(true /*nothrow*/);
51353944Sdim}
52353944SdimINTERCEPTOR_ATTRIBUTE
53353944Sdimvoid *operator new[](size_t size, std::nothrow_t const&) {
54353944Sdim  OPERATOR_NEW_BODY(true /*nothrow*/);
55353944Sdim}
56353944SdimINTERCEPTOR_ATTRIBUTE
57353944Sdimvoid *operator new(size_t size, std::align_val_t align)
58353944Sdim{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
59353944SdimINTERCEPTOR_ATTRIBUTE
60353944Sdimvoid *operator new[](size_t size, std::align_val_t align)
61353944Sdim{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
62353944SdimINTERCEPTOR_ATTRIBUTE
63353944Sdimvoid *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
64353944Sdim{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
65353944SdimINTERCEPTOR_ATTRIBUTE
66353944Sdimvoid *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
67353944Sdim{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
68353944Sdim
69353944Sdim#define OPERATOR_DELETE_BODY \
70353944Sdim  GET_MALLOC_STACK_TRACE; \
71353944Sdim  if (ptr) MsanDeallocate(&stack, ptr)
72353944Sdim
73353944SdimINTERCEPTOR_ATTRIBUTE
74353944Sdimvoid operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
75353944SdimINTERCEPTOR_ATTRIBUTE
76353944Sdimvoid operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
77353944SdimINTERCEPTOR_ATTRIBUTE
78353944Sdimvoid operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
79353944SdimINTERCEPTOR_ATTRIBUTE
80353944Sdimvoid operator delete[](void *ptr, std::nothrow_t const&) {
81353944Sdim  OPERATOR_DELETE_BODY;
82353944Sdim}
83353944SdimINTERCEPTOR_ATTRIBUTE
84353944Sdimvoid operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
85353944SdimINTERCEPTOR_ATTRIBUTE
86353944Sdimvoid operator delete[](void *ptr, size_t size) NOEXCEPT
87353944Sdim{ OPERATOR_DELETE_BODY; }
88353944SdimINTERCEPTOR_ATTRIBUTE
89353944Sdimvoid operator delete(void *ptr, std::align_val_t align) NOEXCEPT
90353944Sdim{ OPERATOR_DELETE_BODY; }
91353944SdimINTERCEPTOR_ATTRIBUTE
92353944Sdimvoid operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
93353944Sdim{ OPERATOR_DELETE_BODY; }
94353944SdimINTERCEPTOR_ATTRIBUTE
95353944Sdimvoid operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
96353944Sdim{ OPERATOR_DELETE_BODY; }
97353944SdimINTERCEPTOR_ATTRIBUTE
98353944Sdimvoid operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
99353944Sdim{ OPERATOR_DELETE_BODY; }
100353944SdimINTERCEPTOR_ATTRIBUTE
101353944Sdimvoid operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
102353944Sdim{ OPERATOR_DELETE_BODY; }
103353944SdimINTERCEPTOR_ATTRIBUTE
104353944Sdimvoid operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
105353944Sdim{ OPERATOR_DELETE_BODY; }
106353944Sdim
107353944Sdim
108353944Sdim#endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
109