mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-01 14:58:18 +00:00
[msan] Unwind stack before fatal reports (#77168)
Msan does not unwind stack in malloc without origins, but we still need trace for fatal errors.
This commit is contained in:
parent
c54a8ac35a
commit
8980936380
@ -322,6 +322,17 @@ 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())
|
||||
|
||||
// Unwind the stack for fatal error, as the parameter `stack` is
|
||||
// empty without origins.
|
||||
#define GET_FATAL_STACK_TRACE_IF_EMPTY(STACK) \
|
||||
if (msan_inited && (STACK)->size == 0) { \
|
||||
(STACK)->Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, \
|
||||
common_flags()->fast_unwind_on_fatal); \
|
||||
}
|
||||
|
||||
class ScopedThreadLocalStateBackup {
|
||||
public:
|
||||
ScopedThreadLocalStateBackup() { Backup(); }
|
||||
|
@ -180,16 +180,18 @@ void MsanThreadLocalMallocStorage::CommitBack() {
|
||||
|
||||
static void *MsanAllocate(BufferedStackTrace *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;
|
||||
}
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportAllocationSizeTooBig(size, max_malloc_size, stack);
|
||||
}
|
||||
if (UNLIKELY(IsRssLimitExceeded())) {
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportRssLimitExceeded(stack);
|
||||
}
|
||||
MsanThread *t = GetCurrentThread();
|
||||
@ -206,6 +208,7 @@ static void *MsanAllocate(BufferedStackTrace *stack, uptr size, uptr alignment,
|
||||
SetAllocatorOutOfMemory();
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportOutOfMemory(size, stack);
|
||||
}
|
||||
Metadata *meta =
|
||||
@ -288,6 +291,7 @@ static void *MsanCalloc(BufferedStackTrace *stack, uptr nmemb, uptr size) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportCallocOverflow(nmemb, size, stack);
|
||||
}
|
||||
return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
|
||||
@ -344,6 +348,7 @@ void *msan_reallocarray(void *ptr, uptr nmemb, uptr size,
|
||||
errno = errno_ENOMEM;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportReallocArrayOverflow(nmemb, size, stack);
|
||||
}
|
||||
return msan_realloc(ptr, nmemb * size, stack);
|
||||
@ -359,6 +364,7 @@ void *msan_pvalloc(uptr size, BufferedStackTrace *stack) {
|
||||
errno = errno_ENOMEM;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportPvallocOverflow(size, stack);
|
||||
}
|
||||
// pvalloc(0) should allocate one page.
|
||||
@ -371,6 +377,7 @@ void *msan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack) {
|
||||
errno = errno_EINVAL;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportInvalidAlignedAllocAlignment(size, alignment, stack);
|
||||
}
|
||||
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
|
||||
@ -381,6 +388,7 @@ void *msan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack) {
|
||||
errno = errno_EINVAL;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportInvalidAllocationAlignment(alignment, stack);
|
||||
}
|
||||
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
|
||||
@ -391,6 +399,7 @@ int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
|
||||
if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
|
||||
if (AllocatorMayReturnNull())
|
||||
return errno_EINVAL;
|
||||
GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
|
||||
ReportInvalidPosixMemalignAlignment(alignment, stack);
|
||||
}
|
||||
void *ptr = MsanAllocate(stack, size, alignment, false);
|
||||
|
@ -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_IF_EMPTY(&stack); \
|
||||
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_IF_EMPTY(&stack); \
|
||||
ReportOutOfMemory(size, &stack); \
|
||||
} \
|
||||
return res;
|
||||
|
||||
INTERCEPTOR_ATTRIBUTE
|
||||
void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
|
||||
|
@ -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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user