1//===-- sanitizer_new_operators.inc -----------------------------*- 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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Shared OPERATOR_NEW_BODY* macros for sanitizer operator new overrides.
10//
11// All eight variants compose the same per-call setup (a sanitizer-specific
12// stack-trace acquisition) with one of the two chain-handling templates from
13// sanitizer_new_handler.h and two sanitizer-supplied lambdas: an Alloc that
14// invokes the sanitizer's internal allocator (returning nullptr only when
15// storage cannot be obtained) and an OnExhausted that calls the sanitizer's
16// "abort with diagnostic" handler.
17//
18// This file is included after the consuming TU has defined the prerequisite
19// macros listed below. Names reference symbols (e.g. `stack`, `size`) that
20// exist only in the macro's expansion context, so this is an .inc, not a
21// freestanding header.
22//
23// The consuming TU must define before including:
24//
25// SANITIZER_NEW_STACK_TRACE
26// A statement that, when expanded inside an operator new body, puts a
27// BufferedStackTrace named `stack` in scope. e.g. for asan:
28// #define SANITIZER_NEW_STACK_TRACE GET_STACK_TRACE_MALLOC
29//
30// SANITIZER_NEW_REPORT_OOM(size)
31// The sanitizer's noreturn diagnostic path for chain-exhausted OOM.
32// Must call a function that does not return (the framework will run
33// UNREACHABLE() and abort if the macro's expansion ever returns).
34// e.g. for asan:
35// #define SANITIZER_NEW_REPORT_OOM(size) \
36// ReportOutOfMemory(size, &stack)
37//
38// SANITIZER_NEW(size)
39// SANITIZER_NEW_ARRAY(size)
40// SANITIZER_NEW_ALIGNED(size, align)
41// SANITIZER_NEW_ARRAY_ALIGNED(size, align)
42// The sanitizer's four internal alloc helpers. Each must return nullptr
43// only when storage cannot be obtained: every nullptr return is treated
44// as a storage failure by the std::get_new_handler() loop. Other failure
45// modes (e.g. invalid alignment) must cause the helper to abort with a
46// diagnostic.
47//
48//===----------------------------------------------------------------------===//
49
50#ifndef SANITIZER_NEW_STACK_TRACE
51# error "SANITIZER_NEW_STACK_TRACE must be defined before including"
52#endif
53#ifndef SANITIZER_NEW_REPORT_OOM
54# error "SANITIZER_NEW_REPORT_OOM must be defined before including"
55#endif
56#ifndef SANITIZER_NEW
57# error "SANITIZER_NEW must be defined before including"
58#endif
59#ifndef SANITIZER_NEW_ARRAY
60# error "SANITIZER_NEW_ARRAY must be defined before including"
61#endif
62#ifndef SANITIZER_NEW_ALIGNED
63# error "SANITIZER_NEW_ALIGNED must be defined before including"
64#endif
65#ifndef SANITIZER_NEW_ARRAY_ALIGNED
66# error "SANITIZER_NEW_ARRAY_ALIGNED must be defined before including"
67#endif
68
69#define OPERATOR_NEW_BODY \
70 SANITIZER_NEW_STACK_TRACE; \
71 return __sanitizer::NewImplThrowing( \
72 [&]() { return SANITIZER_NEW(size); }, \
73 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
74
75#define OPERATOR_NEW_BODY_NOTHROW \
76 SANITIZER_NEW_STACK_TRACE; \
77 return __sanitizer::NewImplNothrow( \
78 [&]() { return SANITIZER_NEW(size); }, \
79 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
80
81#define OPERATOR_NEW_BODY_ARRAY \
82 SANITIZER_NEW_STACK_TRACE; \
83 return __sanitizer::NewImplThrowing( \
84 [&]() { return SANITIZER_NEW_ARRAY(size); }, \
85 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
86
87#define OPERATOR_NEW_BODY_ARRAY_NOTHROW \
88 SANITIZER_NEW_STACK_TRACE; \
89 return __sanitizer::NewImplNothrow( \
90 [&]() { return SANITIZER_NEW_ARRAY(size); }, \
91 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
92
93#define OPERATOR_NEW_BODY_ALIGN \
94 SANITIZER_NEW_STACK_TRACE; \
95 return __sanitizer::NewImplThrowing( \
96 [&]() { return SANITIZER_NEW_ALIGNED(size, align); }, \
97 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
98
99#define OPERATOR_NEW_BODY_ALIGN_NOTHROW \
100 SANITIZER_NEW_STACK_TRACE; \
101 return __sanitizer::NewImplNothrow( \
102 [&]() { return SANITIZER_NEW_ALIGNED(size, align); }, \
103 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
104
105#define OPERATOR_NEW_BODY_ALIGN_ARRAY \
106 SANITIZER_NEW_STACK_TRACE; \
107 return __sanitizer::NewImplThrowing( \
108 [&]() { return SANITIZER_NEW_ARRAY_ALIGNED(size, align); }, \
109 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
110
111#define OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW \
112 SANITIZER_NEW_STACK_TRACE; \
113 return __sanitizer::NewImplNothrow( \
114 [&]() { return SANITIZER_NEW_ARRAY_ALIGNED(size, align); }, \
115 [&]() { SANITIZER_NEW_REPORT_OOM(size); })
116