[compiler-rt] [msan] Unwind stack before fatal reports (PR #77168)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 5 18:43:21 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: Vitaly Buka (vitalybuka)
<details>
<summary>Changes</summary>
Msan does not unwind stack in malloc without origins, but we still need trace
for fatal errors.
---
Full diff: https://github.com/llvm/llvm-project/pull/77168.diff
4 Files Affected:
- (modified) compiler-rt/lib/msan/msan.h (+3)
- (modified) compiler-rt/lib/msan/msan_allocator.cpp (+19-10)
- (modified) compiler-rt/lib/msan/msan_new_delete.cpp (+16-10)
- (modified) compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp (+9-1)
``````````diff
diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h
index 25fa2212bdadd3..b717161577a1db 100644
--- a/compiler-rt/lib/msan/msan.h
+++ b/compiler-rt/lib/msan/msan.h
@@ -321,6 +321,9 @@ const int STACK_TRACE_TAG_VPTR = STACK_TRACE_TAG_FIELDS + 1;
stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal); \
}
+#define GET_FATAL_STACK_TRACE \
+ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME())
+
class ScopedThreadLocalStateBackup {
public:
ScopedThreadLocalStateBackup() { Backup(); }
diff --git a/compiler-rt/lib/msan/msan_allocator.cpp b/compiler-rt/lib/msan/msan_allocator.cpp
index 72a7f980d39fb0..f71f59cedf820e 100644
--- a/compiler-rt/lib/msan/msan_allocator.cpp
+++ b/compiler-rt/lib/msan/msan_allocator.cpp
@@ -180,17 +180,19 @@ void MsanThreadLocalMallocStorage::CommitBack() {
static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
bool zeroise) {
- if (size > max_malloc_size) {
+ if (UNLIKELY(size > max_malloc_size)) {
if (AllocatorMayReturnNull()) {
Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size);
return nullptr;
}
- ReportAllocationSizeTooBig(size, max_malloc_size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportAllocationSizeTooBig(size, max_malloc_size, &stack);
}
if (UNLIKELY(IsRssLimitExceeded())) {
if (AllocatorMayReturnNull())
return nullptr;
- ReportRssLimitExceeded(stack);
+ GET_FATAL_STACK_TRACE;
+ ReportRssLimitExceeded(&stack);
}
MsanThread *t = GetCurrentThread();
void *allocated;
@@ -206,7 +208,8 @@ static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
SetAllocatorOutOfMemory();
if (AllocatorMayReturnNull())
return nullptr;
- ReportOutOfMemory(size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportOutOfMemory(size, &stack);
}
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
@@ -288,7 +291,8 @@ static void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
if (AllocatorMayReturnNull())
return nullptr;
- ReportCallocOverflow(nmemb, size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportCallocOverflow(nmemb, size, &stack);
}
return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
}
@@ -343,7 +347,8 @@ void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
errno = errno_ENOMEM;
if (AllocatorMayReturnNull())
return nullptr;
- ReportReallocArrayOverflow(nmemb, size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportReallocArrayOverflow(nmemb, size, &stack);
}
return msan_realloc(ptr, nmemb * size, stack);
}
@@ -358,7 +363,8 @@ void *msan_pvalloc(uptr size, StackTrace *stack) {
errno = errno_ENOMEM;
if (AllocatorMayReturnNull())
return nullptr;
- ReportPvallocOverflow(size, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportPvallocOverflow(size, &stack);
}
// pvalloc(0) should allocate one page.
size = size ? RoundUpTo(size, PageSize) : PageSize;
@@ -370,7 +376,8 @@ void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) {
errno = errno_EINVAL;
if (AllocatorMayReturnNull())
return nullptr;
- ReportInvalidAlignedAllocAlignment(size, alignment, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportInvalidAlignedAllocAlignment(size, alignment, &stack);
}
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
}
@@ -380,7 +387,8 @@ void *msan_memalign(uptr alignment, uptr size, StackTrace *stack) {
errno = errno_EINVAL;
if (AllocatorMayReturnNull())
return nullptr;
- ReportInvalidAllocationAlignment(alignment, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportInvalidAllocationAlignment(alignment, &stack);
}
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
}
@@ -390,7 +398,8 @@ int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
if (AllocatorMayReturnNull())
return errno_EINVAL;
- ReportInvalidPosixMemalignAlignment(alignment, stack);
+ GET_FATAL_STACK_TRACE;
+ ReportInvalidPosixMemalignAlignment(alignment, &stack);
}
void *ptr = MsanAllocate(stack, size, alignment, false);
if (UNLIKELY(!ptr))
diff --git a/compiler-rt/lib/msan/msan_new_delete.cpp b/compiler-rt/lib/msan/msan_new_delete.cpp
index d4e95c0f65137d..3329a05cca2a86 100644
--- a/compiler-rt/lib/msan/msan_new_delete.cpp
+++ b/compiler-rt/lib/msan/msan_new_delete.cpp
@@ -30,16 +30,22 @@ namespace std {
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
-#define OPERATOR_NEW_BODY(nothrow) \
- GET_MALLOC_STACK_TRACE; \
- void *res = msan_malloc(size, &stack);\
- if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
- return res
-#define OPERATOR_NEW_BODY_ALIGN(nothrow) \
- GET_MALLOC_STACK_TRACE;\
- void *res = msan_memalign((uptr)align, size, &stack);\
- if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
- return res;
+# define OPERATOR_NEW_BODY(nothrow) \
+ GET_MALLOC_STACK_TRACE; \
+ void *res = msan_malloc(size, &stack); \
+ if (!nothrow && UNLIKELY(!res)) { \
+ GET_FATAL_STACK_TRACE; \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ return res
+# define OPERATOR_NEW_BODY_ALIGN(nothrow) \
+ GET_MALLOC_STACK_TRACE; \
+ void *res = msan_memalign((uptr)align, size, &stack); \
+ if (!nothrow && UNLIKELY(!res)) { \
+ GET_FATAL_STACK_TRACE; \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ return res;
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
diff --git a/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp b/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp
index ace28965f3c1ba..c74f241c32b754 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/max_allocation_size.cpp
@@ -35,7 +35,7 @@
// RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH
// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \
// RUN: %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
-// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \
+// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0:fast_unwind_on_malloc=0 \
// RUN: not %run %t strndup 2>&1 | FileCheck %s --check-prefix=CHECK-sCRASH
// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \
// RUN: %run %t strndup 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
@@ -123,20 +123,28 @@ int main(int Argc, char **Argv) {
}
// CHECK-mCRASH: malloc:
+// CHECK-mCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-mCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-cCRASH: calloc:
+// CHECK-cCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-cCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-rCRASH: realloc:
+// CHECK-rCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-rCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-mrCRASH: realloc-after-malloc:
+// CHECK-mrCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-mrCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-nCRASH: new:
+// CHECK-nCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-nCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-nCRASH-OOM: new:
+// CHECK-nCRASH-OOM: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-nCRASH-OOM: {{SUMMARY: .*Sanitizer: out-of-memory}}
// CHECK-nnCRASH: new-nothrow:
+// CHECK-nnCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-nnCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-sCRASH: strndup:
+// CHECK-sCRASH: #{{[0-9]+.*}}max_allocation_size.cpp
// CHECK-sCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
// CHECK-NULL: {{malloc|calloc|calloc-overflow|realloc|realloc-after-malloc|new-nothrow|strndup}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/77168
More information about the llvm-commits
mailing list