[compiler-rt] r334843 - [scudo] Add verbose failures in place of CHECK(0)
Kostya Kortchinsky via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 15 09:45:19 PDT 2018
Author: cryptoad
Date: Fri Jun 15 09:45:19 2018
New Revision: 334843
URL: http://llvm.org/viewvc/llvm-project?rev=334843&view=rev
Log:
[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
Added:
compiler-rt/trunk/lib/scudo/scudo_errors.cpp
compiler-rt/trunk/lib/scudo/scudo_errors.h
Modified:
compiler-rt/trunk/lib/scudo/CMakeLists.txt
compiler-rt/trunk/lib/scudo/scudo_allocator.cpp
compiler-rt/trunk/lib/scudo/scudo_allocator_secondary.h
compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp
compiler-rt/trunk/test/scudo/aligned-new.cpp
compiler-rt/trunk/test/scudo/memalign.c
compiler-rt/trunk/test/scudo/sizes.cpp
compiler-rt/trunk/test/scudo/valloc.c
Modified: compiler-rt/trunk/lib/scudo/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/CMakeLists.txt?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/scudo/CMakeLists.txt Fri Jun 15 09:45:19 2018
@@ -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
Modified: compiler-rt/trunk/lib/scudo/scudo_allocator.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_allocator.cpp?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_allocator.cpp (original)
+++ compiler-rt/trunk/lib/scudo/scudo_allocator.cpp Fri Jun 15 09:45:19 2018
@@ -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, up
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));
}
Modified: compiler-rt/trunk/lib/scudo/scudo_allocator_secondary.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_allocator_secondary.h?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_allocator_secondary.h (original)
+++ compiler-rt/trunk/lib/scudo/scudo_allocator_secondary.h Fri Jun 15 09:45:19 2018
@@ -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;
Added: compiler-rt/trunk/lib/scudo/scudo_errors.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_errors.cpp?rev=334843&view=auto
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_errors.cpp (added)
+++ compiler-rt/trunk/lib/scudo/scudo_errors.cpp Fri Jun 15 09:45:19 2018
@@ -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
Added: compiler-rt/trunk/lib/scudo/scudo_errors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_errors.h?rev=334843&view=auto
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_errors.h (added)
+++ compiler-rt/trunk/lib/scudo/scudo_errors.h Fri Jun 15 09:45:19 2018
@@ -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_
Modified: compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp (original)
+++ compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp Fri Jun 15 09:45:19 2018
@@ -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)
Modified: compiler-rt/trunk/test/scudo/aligned-new.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/scudo/aligned-new.cpp?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/test/scudo/aligned-new.cpp (original)
+++ compiler-rt/trunk/test/scudo/aligned-new.cpp Fri Jun 15 09:45:19 2018
@@ -1,6 +1,7 @@
// RUN: %clangxx_scudo -std=c++1z -faligned-allocation %s -o %t
-// RUN: %run %t valid 2>&1
-// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
+// RUN: %run %t valid 2>&1
+// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t invalid 2>&1 | FileCheck %s
// Tests that the C++17 aligned new/delete operators are working as expected.
// Currently we do not check the consistency of the alignment on deallocation,
@@ -77,6 +78,7 @@ int main(int argc, char **argv) {
const size_t alignment = (1U << 8) - 1;
void *p = operator new(1, static_cast<std::align_val_t>(alignment),
std::nothrow);
+ // CHECK: Scudo ERROR: invalid allocation alignment
assert(!p);
}
Modified: compiler-rt/trunk/test/scudo/memalign.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/scudo/memalign.c?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/test/scudo/memalign.c (original)
+++ compiler-rt/trunk/test/scudo/memalign.c Fri Jun 15 09:45:19 2018
@@ -1,6 +1,6 @@
// RUN: %clang_scudo %s -o %t
// RUN: %run %t valid 2>&1
-// RUN: not %run %t invalid 2>&1
+// RUN: not %run %t invalid 2>&1 | FileCheck --check-prefix=CHECK-align %s
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
// RUN: not %run %t double-free 2>&1 | FileCheck --check-prefix=CHECK-double-free %s
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t realloc 2>&1 | FileCheck --check-prefix=CHECK-realloc %s
@@ -66,6 +66,7 @@ int main(int argc, char **argv)
if (!strcmp(argv[1], "invalid")) {
// Alignment is not a power of 2.
p = memalign(alignment - 1, size);
+ // CHECK-align: Scudo ERROR: invalid allocation alignment
assert(!p);
// Size is not a multiple of alignment.
p = aligned_alloc(alignment, size >> 1);
Modified: compiler-rt/trunk/test/scudo/sizes.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/scudo/sizes.cpp?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/test/scudo/sizes.cpp (original)
+++ compiler-rt/trunk/test/scudo/sizes.cpp Fri Jun 15 09:45:19 2018
@@ -1,11 +1,11 @@
// RUN: %clangxx_scudo %s -lstdc++ -o %t
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-max
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t malloc 2>&1
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-calloc
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t calloc 2>&1
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s
-// RUN: %env_scudo_opts=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-max
+// RUN: %env_scudo_opts=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-oom
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-max
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1
// RUN: %run %t usable 2>&1
@@ -70,4 +70,6 @@ int main(int argc, char **argv) {
return 0;
}
-// CHECK: allocator is terminating the process
+// CHECK-max: {{Scudo ERROR: requested allocation size .* exceeds maximum supported size}}
+// CHECK-oom: Scudo ERROR: allocator is out of memory
+// CHECK-calloc: Scudo ERROR: calloc parameters overflow
Modified: compiler-rt/trunk/test/scudo/valloc.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/scudo/valloc.c?rev=334843&r1=334842&r2=334843&view=diff
==============================================================================
--- compiler-rt/trunk/test/scudo/valloc.c (original)
+++ compiler-rt/trunk/test/scudo/valloc.c Fri Jun 15 09:45:19 2018
@@ -1,6 +1,6 @@
// RUN: %clang_scudo %s -o %t
// RUN: %run %t valid 2>&1
-// RUN: not %run %t invalid 2>&1
+// RUN: not %run %t invalid 2>&1 | FileCheck %s
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
// UNSUPPORTED: android
@@ -54,6 +54,7 @@ int main(int argc, char **argv)
if (!strcmp(argv[1], "invalid")) {
// Size passed to pvalloc overflows when rounded up.
p = pvalloc((size_t)-1);
+ // CHECK: Scudo ERROR: pvalloc parameters overflow
assert(!p);
assert(errno == ENOMEM);
errno = 0;
More information about the llvm-commits
mailing list