2019-08-01 22:22:42 +08:00
|
|
|
//===-- tsan_new_delete.cpp ---------------------------------------------===//
|
2015-04-28 03:33:55 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2015-04-28 03:33:55 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of ThreadSanitizer (TSan), a race detector.
|
|
|
|
//
|
|
|
|
// Interceptors for operators new and delete.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2015-11-06 19:07:26 +08:00
|
|
|
#include "interception/interception.h"
|
2017-06-29 05:58:57 +08:00
|
|
|
#include "sanitizer_common/sanitizer_allocator.h"
|
[TSan] Report proper error on allocator failures instead of CHECK(0)-ing
Summary:
Following up on and complementing D44404 and other sanitizer allocators.
Currently many allocator specific errors (OOM, for example) are reported as
a text message and CHECK(0) termination, no stack, no details, not too
helpful nor informative. To improve the situation, detailed and structured
common errors were defined and reported under the appropriate conditions.
Common tests were generalized a bit to cover a slightly different TSan
stack reporting format, extended to verify errno value and returned
pointer value check is now explicit to facilitate debugging.
Reviewers: dvyukov
Subscribers: srhines, kubamracek, delcypher, #sanitizers, llvm-commits
Differential Revision: https://reviews.llvm.org/D48087
llvm-svn: 334975
2018-06-19 04:03:31 +08:00
|
|
|
#include "sanitizer_common/sanitizer_allocator_report.h"
|
2015-11-11 23:15:14 +08:00
|
|
|
#include "sanitizer_common/sanitizer_internal_defs.h"
|
2015-04-28 03:33:55 +08:00
|
|
|
#include "tsan_interceptors.h"
|
[TSan] Report proper error on allocator failures instead of CHECK(0)-ing
Summary:
Following up on and complementing D44404 and other sanitizer allocators.
Currently many allocator specific errors (OOM, for example) are reported as
a text message and CHECK(0) termination, no stack, no details, not too
helpful nor informative. To improve the situation, detailed and structured
common errors were defined and reported under the appropriate conditions.
Common tests were generalized a bit to cover a slightly different TSan
stack reporting format, extended to verify errno value and returned
pointer value check is now explicit to facilitate debugging.
Reviewers: dvyukov
Subscribers: srhines, kubamracek, delcypher, #sanitizers, llvm-commits
Differential Revision: https://reviews.llvm.org/D48087
llvm-svn: 334975
2018-06-19 04:03:31 +08:00
|
|
|
#include "tsan_rtl.h"
|
2015-04-28 03:33:55 +08:00
|
|
|
|
2019-09-12 07:19:48 +08:00
|
|
|
using namespace __tsan;
|
2015-04-28 03:33:55 +08:00
|
|
|
|
|
|
|
namespace std {
|
|
|
|
struct nothrow_t {};
|
2017-12-23 01:02:17 +08:00
|
|
|
enum class align_val_t: __sanitizer::uptr {};
|
2015-04-28 03:33:55 +08:00
|
|
|
} // namespace std
|
|
|
|
|
2015-11-06 19:07:26 +08:00
|
|
|
DECLARE_REAL(void *, malloc, uptr size)
|
|
|
|
DECLARE_REAL(void, free, void *ptr)
|
|
|
|
|
2017-06-29 05:58:57 +08:00
|
|
|
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
|
|
|
|
#define OPERATOR_NEW_BODY(mangled_name, nothrow) \
|
2019-02-12 16:11:07 +08:00
|
|
|
if (in_symbolizer()) \
|
2016-06-07 02:18:47 +08:00
|
|
|
return InternalAlloc(size); \
|
2015-04-28 03:33:55 +08:00
|
|
|
void *p = 0; \
|
|
|
|
{ \
|
|
|
|
SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
|
|
|
|
p = user_alloc(thr, pc, size); \
|
[TSan] Report proper error on allocator failures instead of CHECK(0)-ing
Summary:
Following up on and complementing D44404 and other sanitizer allocators.
Currently many allocator specific errors (OOM, for example) are reported as
a text message and CHECK(0) termination, no stack, no details, not too
helpful nor informative. To improve the situation, detailed and structured
common errors were defined and reported under the appropriate conditions.
Common tests were generalized a bit to cover a slightly different TSan
stack reporting format, extended to verify errno value and returned
pointer value check is now explicit to facilitate debugging.
Reviewers: dvyukov
Subscribers: srhines, kubamracek, delcypher, #sanitizers, llvm-commits
Differential Revision: https://reviews.llvm.org/D48087
llvm-svn: 334975
2018-06-19 04:03:31 +08:00
|
|
|
if (!nothrow && UNLIKELY(!p)) { \
|
|
|
|
GET_STACK_TRACE_FATAL(thr, pc); \
|
|
|
|
ReportOutOfMemory(size, &stack); \
|
|
|
|
} \
|
2015-04-28 03:33:55 +08:00
|
|
|
} \
|
|
|
|
invoke_malloc_hook(p, size); \
|
|
|
|
return p;
|
|
|
|
|
2017-12-23 01:02:17 +08:00
|
|
|
#define OPERATOR_NEW_BODY_ALIGN(mangled_name, nothrow) \
|
2019-02-12 16:11:07 +08:00
|
|
|
if (in_symbolizer()) \
|
2017-12-23 01:02:17 +08:00
|
|
|
return InternalAlloc(size, nullptr, (uptr)align); \
|
|
|
|
void *p = 0; \
|
|
|
|
{ \
|
|
|
|
SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
|
|
|
|
p = user_memalign(thr, pc, (uptr)align, size); \
|
[TSan] Report proper error on allocator failures instead of CHECK(0)-ing
Summary:
Following up on and complementing D44404 and other sanitizer allocators.
Currently many allocator specific errors (OOM, for example) are reported as
a text message and CHECK(0) termination, no stack, no details, not too
helpful nor informative. To improve the situation, detailed and structured
common errors were defined and reported under the appropriate conditions.
Common tests were generalized a bit to cover a slightly different TSan
stack reporting format, extended to verify errno value and returned
pointer value check is now explicit to facilitate debugging.
Reviewers: dvyukov
Subscribers: srhines, kubamracek, delcypher, #sanitizers, llvm-commits
Differential Revision: https://reviews.llvm.org/D48087
llvm-svn: 334975
2018-06-19 04:03:31 +08:00
|
|
|
if (!nothrow && UNLIKELY(!p)) { \
|
|
|
|
GET_STACK_TRACE_FATAL(thr, pc); \
|
|
|
|
ReportOutOfMemory(size, &stack); \
|
|
|
|
} \
|
2017-12-23 01:02:17 +08:00
|
|
|
} \
|
|
|
|
invoke_malloc_hook(p, size); \
|
|
|
|
return p;
|
|
|
|
|
2015-04-28 03:33:55 +08:00
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new(__sanitizer::uptr size);
|
|
|
|
void *operator new(__sanitizer::uptr size) {
|
2017-06-29 05:58:57 +08:00
|
|
|
OPERATOR_NEW_BODY(_Znwm, false /*nothrow*/);
|
2015-04-28 03:33:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new[](__sanitizer::uptr size);
|
|
|
|
void *operator new[](__sanitizer::uptr size) {
|
2017-06-29 05:58:57 +08:00
|
|
|
OPERATOR_NEW_BODY(_Znam, false /*nothrow*/);
|
2015-04-28 03:33:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
|
|
|
|
void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
|
2017-06-29 05:58:57 +08:00
|
|
|
OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t, true /*nothrow*/);
|
2015-04-28 03:33:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
|
|
|
|
void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
|
2017-06-29 05:58:57 +08:00
|
|
|
OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/);
|
2015-04-28 03:33:55 +08:00
|
|
|
}
|
|
|
|
|
2017-12-23 01:02:17 +08:00
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new(__sanitizer::uptr size, std::align_val_t align);
|
|
|
|
void *operator new(__sanitizer::uptr size, std::align_val_t align) {
|
|
|
|
OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new[](__sanitizer::uptr size, std::align_val_t align);
|
|
|
|
void *operator new[](__sanitizer::uptr size, std::align_val_t align) {
|
|
|
|
OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new(__sanitizer::uptr size, std::align_val_t align,
|
|
|
|
std::nothrow_t const&);
|
|
|
|
void *operator new(__sanitizer::uptr size, std::align_val_t align,
|
|
|
|
std::nothrow_t const&) {
|
|
|
|
OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_tRKSt9nothrow_t,
|
|
|
|
true /*nothrow*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void *operator new[](__sanitizer::uptr size, std::align_val_t align,
|
|
|
|
std::nothrow_t const&);
|
|
|
|
void *operator new[](__sanitizer::uptr size, std::align_val_t align,
|
|
|
|
std::nothrow_t const&) {
|
|
|
|
OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_tRKSt9nothrow_t,
|
|
|
|
true /*nothrow*/);
|
|
|
|
}
|
|
|
|
|
2015-04-28 03:33:55 +08:00
|
|
|
#define OPERATOR_DELETE_BODY(mangled_name) \
|
|
|
|
if (ptr == 0) return; \
|
2019-02-12 16:11:07 +08:00
|
|
|
if (in_symbolizer()) \
|
2016-06-07 02:18:47 +08:00
|
|
|
return InternalFree(ptr); \
|
2015-04-28 03:33:55 +08:00
|
|
|
invoke_free_hook(ptr); \
|
|
|
|
SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \
|
|
|
|
user_free(thr, pc, ptr);
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
2015-08-10 23:24:22 +08:00
|
|
|
void operator delete(void *ptr) NOEXCEPT;
|
|
|
|
void operator delete(void *ptr) NOEXCEPT {
|
2015-04-28 03:33:55 +08:00
|
|
|
OPERATOR_DELETE_BODY(_ZdlPv);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
2015-08-10 23:24:22 +08:00
|
|
|
void operator delete[](void *ptr) NOEXCEPT;
|
|
|
|
void operator delete[](void *ptr) NOEXCEPT {
|
2015-04-28 03:33:55 +08:00
|
|
|
OPERATOR_DELETE_BODY(_ZdaPv);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete(void *ptr, std::nothrow_t const&);
|
|
|
|
void operator delete(void *ptr, std::nothrow_t const&) {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete[](void *ptr, std::nothrow_t const&);
|
|
|
|
void operator delete[](void *ptr, std::nothrow_t const&) {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
|
|
|
|
}
|
2017-12-23 01:02:17 +08:00
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT;
|
|
|
|
void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdlPvm);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT;
|
|
|
|
void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdaPvm);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete(void *ptr, std::align_val_t align) NOEXCEPT;
|
|
|
|
void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT;
|
|
|
|
void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&);
|
|
|
|
void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete[](void *ptr, std::align_val_t align,
|
|
|
|
std::nothrow_t const&);
|
|
|
|
void operator delete[](void *ptr, std::align_val_t align,
|
|
|
|
std::nothrow_t const&) {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete(void *ptr, __sanitizer::uptr size,
|
|
|
|
std::align_val_t align) NOEXCEPT;
|
|
|
|
void operator delete(void *ptr, __sanitizer::uptr size,
|
|
|
|
std::align_val_t align) NOEXCEPT {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void operator delete[](void *ptr, __sanitizer::uptr size,
|
|
|
|
std::align_val_t align) NOEXCEPT;
|
|
|
|
void operator delete[](void *ptr, __sanitizer::uptr size,
|
|
|
|
std::align_val_t align) NOEXCEPT {
|
|
|
|
OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t);
|
|
|
|
}
|