summaryrefslogtreecommitdiff
path: root/lib/scudo/scudo_allocator.cpp
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
commita8f6940aafd86848e846cd811cafaaa3aa0fab70 (patch)
treef8cfdab75adaeb92bf9935366c8e3ccc00402d0a /lib/scudo/scudo_allocator.cpp
parente8b47a537f4c849e66e450dadddfbfe03d1f06fd (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@334843 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/scudo/scudo_allocator.cpp')
-rw-r--r--lib/scudo/scudo_allocator.cpp65
1 files changed, 42 insertions, 23 deletions
diff --git a/lib/scudo/scudo_allocator.cpp b/lib/scudo/scudo_allocator.cpp
index fba4b5ac0..0033328a6 100644
--- a/lib/scudo/scudo_allocator.cpp
+++ b/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));
}