Skip to content

asan: refactor new/delete interceptor macros #146696

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 2, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 85 additions & 62 deletions compiler-rt/lib/asan/asan_new_delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,42 @@ enum class align_val_t: size_t {};
// TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM.
// For local pool allocation, align to SHADOW_GRANULARITY to match asan
// allocator behavior.
#define OPERATOR_NEW_BODY(type, nothrow) \
GET_STACK_TRACE_MALLOC; \
void *res = asan_memalign(0, size, &stack, type); \
if (!nothrow && UNLIKELY(!res)) \
ReportOutOfMemory(size, &stack); \
return res;
#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \
GET_STACK_TRACE_MALLOC; \
void *res = asan_memalign((uptr)align, size, &stack, type); \
if (!nothrow && UNLIKELY(!res)) \
ReportOutOfMemory(size, &stack); \
return res;
#define OPERATOR_NEW_BODY \
GET_STACK_TRACE_MALLOC; \
void *res = asan_memalign(0, size, &stack, FROM_NEW); \
if (UNLIKELY(!res)) \
ReportOutOfMemory(size, &stack); \
return res
#define OPERATOR_NEW_BODY_NOTHROW \
GET_STACK_TRACE_MALLOC; \
return asan_memalign(0, size, &stack, FROM_NEW)
#define OPERATOR_NEW_BODY_ARRAY \
GET_STACK_TRACE_MALLOC; \
void *res = asan_memalign(0, size, &stack, FROM_NEW_BR); \
if (UNLIKELY(!res)) \
ReportOutOfMemory(size, &stack); \
return res
#define OPERATOR_NEW_BODY_ARRAY_NOTHROW \
GET_STACK_TRACE_MALLOC; \
return asan_memalign(0, size, &stack, FROM_NEW_BR)
#define OPERATOR_NEW_BODY_ALIGN \
GET_STACK_TRACE_MALLOC; \
void *res = asan_memalign((uptr)align, size, &stack, FROM_NEW); \
if (UNLIKELY(!res)) \
ReportOutOfMemory(size, &stack); \
return res
#define OPERATOR_NEW_BODY_ALIGN_NOTHROW \
GET_STACK_TRACE_MALLOC; \
return asan_memalign((uptr)align, size, &stack, FROM_NEW)
#define OPERATOR_NEW_BODY_ALIGN_ARRAY \
GET_STACK_TRACE_MALLOC; \
void *res = asan_memalign((uptr)align, size, &stack, FROM_NEW_BR); \
if (UNLIKELY(!res)) \
ReportOutOfMemory(size, &stack); \
return res
#define OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW \
GET_STACK_TRACE_MALLOC; \
return asan_memalign((uptr)align, size, &stack, FROM_NEW_BR)

// On OS X it's not enough to just provide our own 'operator new' and
// 'operator delete' implementations, because they're going to be in the
Expand All @@ -82,129 +106,128 @@ enum class align_val_t: size_t {};
// OS X we need to intercept them using their mangled names.
#if !SANITIZER_APPLE
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size) {
OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
}
void *operator new(size_t size) { OPERATOR_NEW_BODY; }
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size) {
OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
}
void *operator new[](size_t size) { OPERATOR_NEW_BODY_ARRAY; }
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size, std::nothrow_t const &) {
OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
OPERATOR_NEW_BODY_NOTHROW;
}
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size, std::nothrow_t const &) {
OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
OPERATOR_NEW_BODY_ARRAY_NOTHROW;
}
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size, std::align_val_t align) {
OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/);
OPERATOR_NEW_BODY_ALIGN;
}
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size, std::align_val_t align) {
OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/);
OPERATOR_NEW_BODY_ALIGN_ARRAY;
}
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size, std::align_val_t align,
std::nothrow_t const &) {
OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/);
OPERATOR_NEW_BODY_ALIGN_NOTHROW;
}
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size, std::align_val_t align,
std::nothrow_t const &) {
OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/);
OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW;
}

#else // SANITIZER_APPLE
INTERCEPTOR(void *, _Znwm, size_t size) {
OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
}
INTERCEPTOR(void *, _Znam, size_t size) {
OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
}
INTERCEPTOR(void *, _Znwm, size_t size) { OPERATOR_NEW_BODY; }
INTERCEPTOR(void *, _Znam, size_t size) { OPERATOR_NEW_BODY_ARRAY; }
INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
OPERATOR_NEW_BODY_NOTHROW;
}
INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
OPERATOR_NEW_BODY_ARRAY_NOTHROW;
}
#endif // !SANITIZER_APPLE

#define OPERATOR_DELETE_BODY(type) \
#define OPERATOR_DELETE_BODY \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, 0, 0, &stack, FROM_NEW)
#define OPERATOR_DELETE_BODY_ARRAY \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, 0, 0, &stack, type);

#define OPERATOR_DELETE_BODY_SIZE(type) \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, size, 0, &stack, type);

#define OPERATOR_DELETE_BODY_ALIGN(type) \
asan_delete(ptr, 0, 0, &stack, FROM_NEW_BR)
#define OPERATOR_DELETE_BODY_ALIGN \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, 0, static_cast<uptr>(align), &stack, FROM_NEW)
#define OPERATOR_DELETE_BODY_ALIGN_ARRAY \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type);

#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \
asan_delete(ptr, 0, static_cast<uptr>(align), &stack, FROM_NEW_BR)
#define OPERATOR_DELETE_BODY_SIZE \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, size, 0, &stack, FROM_NEW)
#define OPERATOR_DELETE_BODY_SIZE_ARRAY \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, size, 0, &stack, FROM_NEW_BR)
#define OPERATOR_DELETE_BODY_SIZE_ALIGN \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, size, static_cast<uptr>(align), &stack, FROM_NEW)
#define OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY \
GET_STACK_TRACE_FREE; \
asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);
asan_delete(ptr, size, static_cast<uptr>(align), &stack, FROM_NEW_BR)

#if !SANITIZER_APPLE
CXX_OPERATOR_ATTRIBUTE
void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); }
void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
CXX_OPERATOR_ATTRIBUTE
void operator delete[](void *ptr) NOEXCEPT {
OPERATOR_DELETE_BODY(FROM_NEW_BR);
}
void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY_ARRAY; }
CXX_OPERATOR_ATTRIBUTE
void operator delete(void *ptr, std::nothrow_t const &) {
OPERATOR_DELETE_BODY(FROM_NEW);
OPERATOR_DELETE_BODY;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete[](void *ptr, std::nothrow_t const &) {
OPERATOR_DELETE_BODY(FROM_NEW_BR);
OPERATOR_DELETE_BODY_ARRAY;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete(void *ptr, size_t size) NOEXCEPT {
OPERATOR_DELETE_BODY_SIZE(FROM_NEW);
OPERATOR_DELETE_BODY_SIZE;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete[](void *ptr, size_t size) NOEXCEPT {
OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR);
OPERATOR_DELETE_BODY_SIZE_ARRAY;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
OPERATOR_DELETE_BODY_ALIGN;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
OPERATOR_DELETE_BODY_ALIGN_ARRAY;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete(void *ptr, std::align_val_t align,
std::nothrow_t const &) {
OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
OPERATOR_DELETE_BODY_ALIGN;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete[](void *ptr, std::align_val_t align,
std::nothrow_t const &) {
OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
OPERATOR_DELETE_BODY_ALIGN_ARRAY;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT {
OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW);
OPERATOR_DELETE_BODY_SIZE_ALIGN;
}
CXX_OPERATOR_ATTRIBUTE
void operator delete[](void *ptr, size_t size,
std::align_val_t align) NOEXCEPT {
OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR);
OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY;
}

#else // SANITIZER_APPLE
INTERCEPTOR(void, _ZdlPv, void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW); }
INTERCEPTOR(void, _ZdaPv, void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
INTERCEPTOR(void, _ZdlPv, void *ptr) { OPERATOR_DELETE_BODY; }
INTERCEPTOR(void, _ZdaPv, void *ptr) { OPERATOR_DELETE_BODY_ARRAY; }
INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const &) {
OPERATOR_DELETE_BODY(FROM_NEW);
OPERATOR_DELETE_BODY;
}
INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const &) {
OPERATOR_DELETE_BODY(FROM_NEW_BR);
OPERATOR_DELETE_BODY_ARRAY;
}
#endif // !SANITIZER_APPLE
Loading