summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/scudo
diff options
context:
space:
mode:
authorKostya Kortchinsky <kostyak@google.com>2018-06-15 16:45:19 +0000
committerKostya Kortchinsky <kostyak@google.com>2018-06-15 16:45:19 +0000
commit4adf24502ec8c993e3da2fe0ad2f4921e5a76bb9 (patch)
treed67950f68ed4bb6455dcaf9a9041a235d274fadd /compiler-rt/lib/scudo
parenta6edca72ba6962455ab427759b9380555db0d211 (diff)
downloadbcm5719-llvm-4adf24502ec8c993e3da2fe0ad2f4921e5a76bb9.tar.gz
bcm5719-llvm-4adf24502ec8c993e3da2fe0ad2f4921e5a76bb9.zip
[scudo] Add verbose failures in place of CHECK(0)
Summary: The current `FailureHandler` mechanism was fairly opaque with regard to the failure reason due to using `CHECK(0)`. Scudo is a bit different from the other Sanitizers as it prefers to avoid spurious processing in its failure path. So we just `dieWithMessage` using a somewhat explicit string. Adapted the tests for the new strings. While this takes care of the `OnBadRequest` & `OnOOM` failures, the next step is probably to migrate the other Scudo failures in the same failes (header corruption, invalid state and so on). Reviewers: alekseyshl Reviewed By: alekseyshl Subscribers: filcab, mgorny, delcypher, #sanitizers, llvm-commits Differential Revision: https://reviews.llvm.org/D48199 llvm-svn: 334843
Diffstat (limited to 'compiler-rt/lib/scudo')
-rw-r--r--compiler-rt/lib/scudo/CMakeLists.txt1
-rw-r--r--compiler-rt/lib/scudo/scudo_allocator.cpp65
-rw-r--r--compiler-rt/lib/scudo/scudo_allocator_secondary.h2
-rw-r--r--compiler-rt/lib/scudo/scudo_errors.cpp77
-rw-r--r--compiler-rt/lib/scudo/scudo_errors.h35
-rw-r--r--compiler-rt/lib/scudo/scudo_new_delete.cpp3
6 files changed, 158 insertions, 25 deletions
diff --git a/compiler-rt/lib/scudo/CMakeLists.txt b/compiler-rt/lib/scudo/CMakeLists.txt
index 3adfe688260..32472af5c8a 100644
--- a/compiler-rt/lib/scudo/CMakeLists.txt
+++ b/compiler-rt/lib/scudo/CMakeLists.txt
@@ -36,6 +36,7 @@ endif()
set(SCUDO_SOURCES
scudo_allocator.cpp
scudo_crc32.cpp
+ scudo_errors.cpp
scudo_flags.cpp
scudo_malloc.cpp
scudo_termination.cpp
diff --git a/compiler-rt/lib/scudo/scudo_allocator.cpp b/compiler-rt/lib/scudo/scudo_allocator.cpp
index fba4b5ac07d..0033328a602 100644
--- a/compiler-rt/lib/scudo/scudo_allocator.cpp
+++ b/compiler-rt/lib/scudo/scudo_allocator.cpp
@@ -16,6 +16,7 @@
#include "scudo_allocator.h"
#include "scudo_crc32.h"
+#include "scudo_errors.h"
#include "scudo_flags.h"
#include "scudo_interface_internal.h"
#include "scudo_tsd.h"
@@ -224,8 +225,6 @@ struct ScudoAllocator {
static const uptr MaxAllowedMallocSize =
FIRST_32_SECOND_64(2UL << 30, 1ULL << 40);
- typedef ReturnNullOrDieOnFailure FailureHandler;
-
ScudoBackendAllocator BackendAllocator;
ScudoQuarantine AllocatorQuarantine;
@@ -360,24 +359,30 @@ struct ScudoAllocator {
void *allocate(uptr Size, uptr Alignment, AllocType Type,
bool ForceZeroContents = false) {
initThreadMaybe();
- if (UNLIKELY(Alignment > MaxAlignment))
- return FailureHandler::OnBadRequest();
+ if (UNLIKELY(Alignment > MaxAlignment)) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ reportAllocationAlignmentTooBig(Alignment, MaxAlignment);
+ }
if (UNLIKELY(Alignment < MinAlignment))
Alignment = MinAlignment;
- if (UNLIKELY(Size >= MaxAllowedMallocSize))
- return FailureHandler::OnBadRequest();
- if (UNLIKELY(Size == 0))
- Size = 1;
- const uptr NeededSize = RoundUpTo(Size, MinAlignment) +
+ const uptr NeededSize = RoundUpTo(Size ? Size : 1, MinAlignment) +
Chunk::getHeaderSize();
const uptr AlignedSize = (Alignment > MinAlignment) ?
NeededSize + (Alignment - Chunk::getHeaderSize()) : NeededSize;
- if (UNLIKELY(AlignedSize >= MaxAllowedMallocSize))
- return FailureHandler::OnBadRequest();
+ if (UNLIKELY(Size >= MaxAllowedMallocSize) ||
+ UNLIKELY(AlignedSize >= MaxAllowedMallocSize)) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ reportAllocationSizeTooBig(Size, AlignedSize, MaxAllowedMallocSize);
+ }
- if (CheckRssLimit && UNLIKELY(isRssLimitExceeded()))
- return FailureHandler::OnOOM();
+ if (CheckRssLimit && UNLIKELY(isRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ reportRssLimitExceeded();
+ }
// Primary and Secondary backed allocations have a different treatment. We
// deal with alignment requirements of Primary serviced allocations here,
@@ -398,8 +403,12 @@ struct ScudoAllocator {
ClassId = 0;
BackendPtr = BackendAllocator.allocateSecondary(BackendSize, Alignment);
}
- if (UNLIKELY(!BackendPtr))
- return FailureHandler::OnOOM();
+ if (UNLIKELY(!BackendPtr)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ reportOutOfMemory(Size);
+ }
// If requested, we will zero out the entire contents of the returned chunk.
if ((ForceZeroContents || ZeroContents) && ClassId)
@@ -573,8 +582,11 @@ struct ScudoAllocator {
void *calloc(uptr NMemB, uptr Size) {
initThreadMaybe();
- if (UNLIKELY(CheckForCallocOverflow(NMemB, Size)))
- return FailureHandler::OnBadRequest();
+ if (UNLIKELY(CheckForCallocOverflow(NMemB, Size))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ reportCallocOverflow(NMemB, Size);
+ }
return allocate(NMemB * Size, MinAlignment, FromMalloc, true);
}
@@ -591,9 +603,9 @@ struct ScudoAllocator {
return stats[StatType];
}
- void *handleBadRequest() {
+ bool canReturnNull() {
initThreadMaybe();
- return FailureHandler::OnBadRequest();
+ return AllocatorMayReturnNull();
}
void setRssLimit(uptr LimitMb, bool HardLimit) {
@@ -632,7 +644,9 @@ void ScudoTSD::commitBack() {
void *scudoAllocate(uptr Size, uptr Alignment, AllocType Type) {
if (Alignment && UNLIKELY(!IsPowerOfTwo(Alignment))) {
errno = EINVAL;
- return Instance.handleBadRequest();
+ if (Instance.canReturnNull())
+ return nullptr;
+ reportAllocationAlignmentNotPowerOfTwo(Alignment);
}
return SetErrnoOnNull(Instance.allocate(Size, Alignment, Type));
}
@@ -664,7 +678,9 @@ void *scudoPvalloc(uptr Size) {
uptr PageSize = GetPageSizeCached();
if (UNLIKELY(CheckForPvallocOverflow(Size, PageSize))) {
errno = ENOMEM;
- return Instance.handleBadRequest();
+ if (Instance.canReturnNull())
+ return nullptr;
+ reportPvallocOverflow(Size);
}
// pvalloc(0) should allocate one page.
Size = Size ? RoundUpTo(Size, PageSize) : PageSize;
@@ -673,7 +689,8 @@ void *scudoPvalloc(uptr Size) {
int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size) {
if (UNLIKELY(!CheckPosixMemalignAlignment(Alignment))) {
- Instance.handleBadRequest();
+ if (!Instance.canReturnNull())
+ reportInvalidPosixMemalignAlignment(Alignment);
return EINVAL;
}
void *Ptr = Instance.allocate(Size, Alignment, FromMemalign);
@@ -686,7 +703,9 @@ int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size) {
void *scudoAlignedAlloc(uptr Alignment, uptr Size) {
if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(Alignment, Size))) {
errno = EINVAL;
- return Instance.handleBadRequest();
+ if (Instance.canReturnNull())
+ return nullptr;
+ reportInvalidAlignedAllocAlignment(Size, Alignment);
}
return SetErrnoOnNull(Instance.allocate(Size, Alignment, FromMalloc));
}
diff --git a/compiler-rt/lib/scudo/scudo_allocator_secondary.h b/compiler-rt/lib/scudo/scudo_allocator_secondary.h
index 27eb444c5f4..425ef4d26cb 100644
--- a/compiler-rt/lib/scudo/scudo_allocator_secondary.h
+++ b/compiler-rt/lib/scudo/scudo_allocator_secondary.h
@@ -87,7 +87,7 @@ class ScudoLargeMmapAllocator {
ReservedAddressRange AddressRange;
uptr ReservedBeg = AddressRange.Init(ReservedSize, SecondaryAllocatorName);
if (UNLIKELY(ReservedBeg == ~static_cast<uptr>(0)))
- return ReturnNullOrDieOnFailure::OnOOM();
+ return nullptr;
// A page-aligned pointer is assumed after that, so check it now.
DCHECK(IsAligned(ReservedBeg, PageSize));
uptr ReservedEnd = ReservedBeg + ReservedSize;
diff --git a/compiler-rt/lib/scudo/scudo_errors.cpp b/compiler-rt/lib/scudo/scudo_errors.cpp
new file mode 100644
index 00000000000..d11e03cf916
--- /dev/null
+++ b/compiler-rt/lib/scudo/scudo_errors.cpp
@@ -0,0 +1,77 @@
+//===-- scudo_errors.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Verbose termination functions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "scudo_utils.h"
+
+#include "sanitizer_common/sanitizer_flags.h"
+
+namespace __scudo {
+
+void NORETURN reportCallocOverflow(uptr Count, uptr Size) {
+ dieWithMessage("calloc parameters overflow: count * size (%zd * %zd) cannot "
+ "be represented with type size_t\n", Count, Size);
+}
+
+void NORETURN reportPvallocOverflow(uptr Size) {
+ dieWithMessage("pvalloc parameters overflow: size 0x%zx rounded up to system "
+ "page size 0x%zx cannot be represented in type size_t\n", Size,
+ GetPageSizeCached());
+}
+
+void NORETURN reportAllocationAlignmentTooBig(uptr Alignment,
+ uptr MaxAlignment) {
+ dieWithMessage("invalid allocation alignment: %zd exceeds maximum supported "
+ "allocation of %zd\n", Alignment, MaxAlignment);
+}
+
+void NORETURN reportAllocationAlignmentNotPowerOfTwo(uptr Alignment) {
+ dieWithMessage("invalid allocation alignment: %zd, alignment must be a power "
+ "of two\n", Alignment);
+}
+
+void NORETURN reportInvalidPosixMemalignAlignment(uptr Alignment) {
+ dieWithMessage("invalid alignment requested in posix_memalign: %zd, alignment"
+ " must be a power of two and a multiple of sizeof(void *) == %zd\n",
+ Alignment, sizeof(void *)); // NOLINT
+}
+
+void NORETURN reportInvalidAlignedAllocAlignment(uptr Size, uptr Alignment) {
+#if SANITIZER_POSIX
+ dieWithMessage("invalid alignment requested in aligned_alloc: %zd, alignment "
+ "must be a power of two and the requested size 0x%zx must be a multiple "
+ "of alignment\n", Alignment, Size);
+#else
+ dieWithMessage("invalid alignment requested in aligned_alloc: %zd, the "
+ "requested size 0x%zx must be a multiple of alignment\n", Alignment,
+ Size);
+#endif
+}
+
+void NORETURN reportAllocationSizeTooBig(uptr UserSize, uptr TotalSize,
+ uptr MaxSize) {
+ dieWithMessage("requested allocation size 0x%zx (0x%zx after adjustments) "
+ "exceeds maximum supported size of 0x%zx\n", UserSize, TotalSize,
+ MaxSize);
+}
+
+void NORETURN reportRssLimitExceeded() {
+ dieWithMessage("specified RSS limit exceeded, currently set to "
+ "soft_rss_limit_mb=%zd\n", common_flags()->soft_rss_limit_mb);
+}
+
+void NORETURN reportOutOfMemory(uptr RequestedSize) {
+ dieWithMessage("allocator is out of memory trying to allocate 0x%zx bytes\n",
+ RequestedSize);
+}
+
+} // namespace __scudo
diff --git a/compiler-rt/lib/scudo/scudo_errors.h b/compiler-rt/lib/scudo/scudo_errors.h
new file mode 100644
index 00000000000..8b1af996be0
--- /dev/null
+++ b/compiler-rt/lib/scudo/scudo_errors.h
@@ -0,0 +1,35 @@
+//===-- scudo_errors.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Header for scudo_errors.cpp.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_ERRORS_H_
+#define SCUDO_ERRORS_H_
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __scudo {
+
+void NORETURN reportCallocOverflow(uptr Count, uptr Size);
+void NORETURN reportPvallocOverflow(uptr Size);
+void NORETURN reportAllocationAlignmentTooBig(uptr Alignment,
+ uptr MaxAlignment);
+void NORETURN reportAllocationAlignmentNotPowerOfTwo(uptr Alignment);
+void NORETURN reportInvalidPosixMemalignAlignment(uptr Alignment);
+void NORETURN reportInvalidAlignedAllocAlignment(uptr Size, uptr Alignment);
+void NORETURN reportAllocationSizeTooBig(uptr UserSize, uptr TotalSize,
+ uptr MaxSize);
+void NORETURN reportRssLimitExceeded();
+void NORETURN reportOutOfMemory(uptr RequestedSize);
+
+} // namespace __scudo
+
+#endif // SCUDO_ERRORS_H_
diff --git a/compiler-rt/lib/scudo/scudo_new_delete.cpp b/compiler-rt/lib/scudo/scudo_new_delete.cpp
index 948d07a5210..daa3b47dc72 100644
--- a/compiler-rt/lib/scudo/scudo_new_delete.cpp
+++ b/compiler-rt/lib/scudo/scudo_new_delete.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "scudo_allocator.h"
+#include "scudo_errors.h"
#include "interception/interception.h"
@@ -30,7 +31,7 @@ enum class align_val_t: size_t {};
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
#define OPERATOR_NEW_BODY_ALIGN(Type, Align, NoThrow) \
void *Ptr = scudoAllocate(size, static_cast<uptr>(Align), Type); \
- if (!NoThrow && UNLIKELY(!Ptr)) DieOnFailure::OnOOM(); \
+ if (!NoThrow && UNLIKELY(!Ptr)) reportOutOfMemory(size); \
return Ptr;
#define OPERATOR_NEW_BODY(Type, NoThrow) \
OPERATOR_NEW_BODY_ALIGN(Type, 0, NoThrow)
OpenPOWER on IntegriCloud