diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-01 13:24:15 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-01 13:24:15 +0000 |
commit | 50aa32eff79f252ab05a0c0a589cf2ca37cd9923 (patch) | |
tree | 26de9fb78670a86ae63c21707b85c414cbf9d012 /lib/lsan | |
parent | 10fcf738d732204a1f1e28878d68a27c5f12cf3b (diff) |
Notes
Diffstat (limited to 'lib/lsan')
-rw-r--r-- | lib/lsan/lsan_allocator.cc | 6 | ||||
-rw-r--r-- | lib/lsan/lsan_interceptors.cc | 67 |
2 files changed, 55 insertions, 18 deletions
diff --git a/lib/lsan/lsan_allocator.cc b/lib/lsan/lsan_allocator.cc index f54e953731b4d..6514aea6f6098 100644 --- a/lib/lsan/lsan_allocator.cc +++ b/lib/lsan/lsan_allocator.cc @@ -74,7 +74,7 @@ void *Allocate(const StackTrace &stack, uptr size, uptr alignment, size = 1; if (size > kMaxAllowedMallocSize) { Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", size); - return nullptr; + return Allocator::FailureHandler::OnBadRequest(); } void *p = allocator.Allocate(GetAllocatorCache(), size, alignment); // Do not rely on the allocator to clear the memory (it's slow). @@ -99,7 +99,7 @@ void *Reallocate(const StackTrace &stack, void *p, uptr new_size, if (new_size > kMaxAllowedMallocSize) { Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", new_size); allocator.Deallocate(GetAllocatorCache(), p); - return nullptr; + return Allocator::FailureHandler::OnBadRequest(); } p = allocator.Reallocate(GetAllocatorCache(), p, new_size, alignment); RegisterAllocation(stack, p, new_size); @@ -134,6 +134,8 @@ void *lsan_realloc(void *p, uptr size, const StackTrace &stack) { } void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack) { + if (CheckForCallocOverflow(size, nmemb)) + return Allocator::FailureHandler::OnBadRequest(); size *= nmemb; return Allocate(stack, size, 1, true); } diff --git a/lib/lsan/lsan_interceptors.cc b/lib/lsan/lsan_interceptors.cc index 9e39a7d1944da..7d514402ad4b1 100644 --- a/lib/lsan/lsan_interceptors.cc +++ b/lib/lsan/lsan_interceptors.cc @@ -70,7 +70,6 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { CHECK(allocated < kCallocPoolSize); return mem; } - if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return nullptr; ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; return lsan_calloc(nmemb, size, stack); @@ -199,24 +198,38 @@ INTERCEPTOR(int, mprobe, void *ptr) { } #endif // SANITIZER_INTERCEPT_MCHECK_MPROBE -#define OPERATOR_NEW_BODY \ - ENSURE_LSAN_INITED; \ - GET_STACK_TRACE_MALLOC; \ - return Allocate(stack, size, 1, kAlwaysClearMemory); -INTERCEPTOR_ATTRIBUTE -void *operator new(size_t size) { OPERATOR_NEW_BODY; } -INTERCEPTOR_ATTRIBUTE -void *operator new[](size_t size) { OPERATOR_NEW_BODY; } -INTERCEPTOR_ATTRIBUTE -void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; } -INTERCEPTOR_ATTRIBUTE -void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; } +// TODO(alekseys): throw std::bad_alloc instead of dying on OOM. +#define OPERATOR_NEW_BODY(nothrow) \ + ENSURE_LSAN_INITED; \ + GET_STACK_TRACE_MALLOC; \ + void *res = Allocate(stack, size, 1, kAlwaysClearMemory);\ + if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\ + return res; #define OPERATOR_DELETE_BODY \ ENSURE_LSAN_INITED; \ Deallocate(ptr); +// 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 runtime +// dylib, and the main executable will depend on both the runtime dylib and +// libstdc++, each of has its implementation of new and delete. +// To make sure that C++ allocation/deallocation operators are overridden on +// OS X we need to intercept them using their mangled names. +#if !SANITIZER_MAC + +INTERCEPTOR_ATTRIBUTE +void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } +INTERCEPTOR_ATTRIBUTE +void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } +INTERCEPTOR_ATTRIBUTE +void *operator new(size_t size, std::nothrow_t const&) +{ OPERATOR_NEW_BODY(true /*nothrow*/); } +INTERCEPTOR_ATTRIBUTE +void *operator new[](size_t size, std::nothrow_t const&) +{ OPERATOR_NEW_BODY(true /*nothrow*/); } + INTERCEPTOR_ATTRIBUTE void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } INTERCEPTOR_ATTRIBUTE @@ -224,9 +237,31 @@ void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } INTERCEPTOR_ATTRIBUTE void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } INTERCEPTOR_ATTRIBUTE -void operator delete[](void *ptr, std::nothrow_t const &) { - OPERATOR_DELETE_BODY; -} +void operator delete[](void *ptr, std::nothrow_t const &) +{ OPERATOR_DELETE_BODY; } + +#else // SANITIZER_MAC + +INTERCEPTOR(void *, _Znwm, size_t size) +{ OPERATOR_NEW_BODY(false /*nothrow*/); } +INTERCEPTOR(void *, _Znam, size_t size) +{ OPERATOR_NEW_BODY(false /*nothrow*/); } +INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) +{ OPERATOR_NEW_BODY(true /*nothrow*/); } +INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) +{ OPERATOR_NEW_BODY(true /*nothrow*/); } + +INTERCEPTOR(void, _ZdlPv, void *ptr) +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR(void, _ZdaPv, void *ptr) +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY; } + +#endif // !SANITIZER_MAC + ///// Thread initialization and finalization. ///// |