forked from OSchip/llvm-project
[sanitizer] Implement reallocarray.
Summary: It's a cross of calloc and realloc. Sanitizers implement calloc-like check for size overflow. Reviewers: vitalybuka, kcc Subscribers: kubamracek, #sanitizers, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D61108 llvm-svn: 359708
This commit is contained in:
parent
9f04d97cd7
commit
d1a710047b
|
@ -87,6 +87,7 @@ extern "C" {
|
|||
void __sanitizer_malloc_stats(void);
|
||||
void * __sanitizer_calloc(size_t nmemb, size_t size);
|
||||
void * __sanitizer_realloc(void *ptr, size_t size);
|
||||
void * __sanitizer_reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
void * __sanitizer_malloc(size_t size);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -879,6 +879,17 @@ void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
|
|||
return SetErrnoOnNull(instance.Calloc(nmemb, size, stack));
|
||||
}
|
||||
|
||||
void *asan_reallocarray(void *p, uptr nmemb, uptr size,
|
||||
BufferedStackTrace *stack) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
|
||||
errno = errno_ENOMEM;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
ReportReallocArrayOverflow(nmemb, size, stack);
|
||||
}
|
||||
return asan_realloc(p, nmemb * size, stack);
|
||||
}
|
||||
|
||||
void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) {
|
||||
if (!p)
|
||||
return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC, true));
|
||||
|
|
|
@ -219,6 +219,8 @@ void asan_delete(void *ptr, uptr size, uptr alignment,
|
|||
void *asan_malloc(uptr size, BufferedStackTrace *stack);
|
||||
void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
|
||||
void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
|
||||
void *asan_reallocarray(void *p, uptr nmemb, uptr size,
|
||||
BufferedStackTrace *stack);
|
||||
void *asan_valloc(uptr size, BufferedStackTrace *stack);
|
||||
void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
|
||||
|
||||
|
|
|
@ -177,6 +177,19 @@ void ErrorCallocOverflow::Print() {
|
|||
ReportErrorSummary(scariness.GetDescription(), stack);
|
||||
}
|
||||
|
||||
void ErrorReallocArrayOverflow::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Error());
|
||||
Report(
|
||||
"ERROR: AddressSanitizer: reallocarray parameters overflow: count * size "
|
||||
"(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
|
||||
count, size, AsanThreadIdAndName(tid).c_str());
|
||||
Printf("%s", d.Default());
|
||||
stack->Print();
|
||||
PrintHintAllocatorCannotReturnNull();
|
||||
ReportErrorSummary(scariness.GetDescription(), stack);
|
||||
}
|
||||
|
||||
void ErrorPvallocOverflow::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Error());
|
||||
|
|
|
@ -163,6 +163,21 @@ struct ErrorCallocOverflow : ErrorBase {
|
|||
void Print();
|
||||
};
|
||||
|
||||
struct ErrorReallocArrayOverflow : ErrorBase {
|
||||
const BufferedStackTrace *stack;
|
||||
uptr count;
|
||||
uptr size;
|
||||
|
||||
ErrorReallocArrayOverflow() = default; // (*)
|
||||
ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
|
||||
uptr size_)
|
||||
: ErrorBase(tid, 10, "reallocarray-overflow"),
|
||||
stack(stack_),
|
||||
count(count_),
|
||||
size(size_) {}
|
||||
void Print();
|
||||
};
|
||||
|
||||
struct ErrorPvallocOverflow : ErrorBase {
|
||||
const BufferedStackTrace *stack;
|
||||
uptr size;
|
||||
|
@ -371,6 +386,7 @@ struct ErrorGeneric : ErrorBase {
|
|||
macro(MallocUsableSizeNotOwned) \
|
||||
macro(SanitizerGetAllocatedSizeNotOwned) \
|
||||
macro(CallocOverflow) \
|
||||
macro(ReallocArrayOverflow) \
|
||||
macro(PvallocOverflow) \
|
||||
macro(InvalidAllocationAlignment) \
|
||||
macro(InvalidAlignedAllocAlignment) \
|
||||
|
|
|
@ -165,6 +165,14 @@ INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
|
|||
return asan_realloc(ptr, size, &stack);
|
||||
}
|
||||
|
||||
#if SANITIZER_INTERCEPT_REALLOCARRAY
|
||||
INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) {
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_reallocarray(ptr, nmemb, size, &stack);
|
||||
}
|
||||
#endif // SANITIZER_INTERCEPT_REALLOCARRAY
|
||||
|
||||
#if SANITIZER_INTERCEPT_MEMALIGN
|
||||
INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
|
|
|
@ -263,6 +263,13 @@ void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack) {
|
|||
in_report.ReportError(error);
|
||||
}
|
||||
|
||||
void ReportReallocArrayOverflow(uptr count, uptr size,
|
||||
BufferedStackTrace *stack) {
|
||||
ScopedInErrorReport in_report(/*fatal*/ true);
|
||||
ErrorReallocArrayOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
|
||||
in_report.ReportError(error);
|
||||
}
|
||||
|
||||
void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack) {
|
||||
ScopedInErrorReport in_report(/*fatal*/ true);
|
||||
ErrorPvallocOverflow error(GetCurrentTidOrInvalid(), stack, size);
|
||||
|
|
|
@ -61,6 +61,8 @@ void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
|
|||
void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack);
|
||||
void ReportReallocArrayOverflow(uptr count, uptr size,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack);
|
||||
void ReportInvalidAllocationAlignment(uptr alignment,
|
||||
BufferedStackTrace *stack);
|
||||
|
|
|
@ -81,6 +81,7 @@ void HwasanAllocatorThreadFinish();
|
|||
void *hwasan_malloc(uptr size, StackTrace *stack);
|
||||
void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack);
|
||||
void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack);
|
||||
void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack);
|
||||
void *hwasan_valloc(uptr size, StackTrace *stack);
|
||||
void *hwasan_pvalloc(uptr size, StackTrace *stack);
|
||||
void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack);
|
||||
|
|
|
@ -341,6 +341,16 @@ void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack) {
|
|||
return SetErrnoOnNull(HwasanReallocate(stack, ptr, size, sizeof(u64)));
|
||||
}
|
||||
|
||||
void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
|
||||
errno = errno_ENOMEM;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
ReportReallocArrayOverflow(nmemb, size, stack);
|
||||
}
|
||||
return hwasan_realloc(ptr, nmemb * size, stack);
|
||||
}
|
||||
|
||||
void *hwasan_valloc(uptr size, StackTrace *stack) {
|
||||
return SetErrnoOnNull(
|
||||
HwasanAllocate(stack, size, GetPageSizeCached(), false));
|
||||
|
|
|
@ -178,6 +178,11 @@ void * __sanitizer_realloc(void *ptr, uptr size) {
|
|||
return hwasan_realloc(ptr, size, &stack);
|
||||
}
|
||||
|
||||
void * __sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) {
|
||||
GET_MALLOC_STACK_TRACE;
|
||||
return hwasan_reallocarray(ptr, nmemb, size, &stack);
|
||||
}
|
||||
|
||||
void * __sanitizer_malloc(uptr size) {
|
||||
GET_MALLOC_STACK_TRACE;
|
||||
if (UNLIKELY(!hwasan_init_is_running))
|
||||
|
@ -204,6 +209,7 @@ INTERCEPTOR_ALIAS(void, free, void *ptr);
|
|||
INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr);
|
||||
INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size);
|
||||
INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size);
|
||||
INTERCEPTOR_ALIAS(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size);
|
||||
INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size);
|
||||
|
||||
#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
|
||||
|
|
|
@ -197,6 +197,9 @@ void * __sanitizer_calloc(uptr nmemb, uptr size);
|
|||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void * __sanitizer_realloc(void *ptr, uptr size);
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void * __sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size);
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void * __sanitizer_malloc(uptr size);
|
||||
|
||||
|
|
|
@ -185,6 +185,17 @@ void *lsan_realloc(void *p, uptr size, const StackTrace &stack) {
|
|||
return SetErrnoOnNull(Reallocate(stack, p, size, 1));
|
||||
}
|
||||
|
||||
void *lsan_reallocarray(void *ptr, uptr nmemb, uptr size,
|
||||
const StackTrace &stack) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
|
||||
errno = errno_ENOMEM;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
ReportReallocArrayOverflow(nmemb, size, &stack);
|
||||
}
|
||||
return lsan_realloc(ptr, nmemb * size, stack);
|
||||
}
|
||||
|
||||
void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack) {
|
||||
return SetErrnoOnNull(Calloc(nmemb, size, stack));
|
||||
}
|
||||
|
|
|
@ -116,6 +116,8 @@ void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack);
|
|||
void *lsan_malloc(uptr size, const StackTrace &stack);
|
||||
void lsan_free(void *p);
|
||||
void *lsan_realloc(void *p, uptr size, const StackTrace &stack);
|
||||
void *lsan_reallocarray(void *p, uptr nmemb, uptr size,
|
||||
const StackTrace &stack);
|
||||
void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack);
|
||||
void *lsan_valloc(uptr size, const StackTrace &stack);
|
||||
void *lsan_pvalloc(uptr size, const StackTrace &stack);
|
||||
|
|
|
@ -83,6 +83,12 @@ INTERCEPTOR(void*, realloc, void *q, uptr size) {
|
|||
return lsan_realloc(q, size, stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) {
|
||||
ENSURE_LSAN_INITED;
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return lsan_reallocarray(q, nmemb, size, stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
|
||||
ENSURE_LSAN_INITED;
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
|
|
|
@ -288,6 +288,7 @@ void MsanDeallocate(StackTrace *stack, void *ptr);
|
|||
void *msan_malloc(uptr size, StackTrace *stack);
|
||||
void *msan_calloc(uptr nmemb, uptr size, StackTrace *stack);
|
||||
void *msan_realloc(void *ptr, uptr size, StackTrace *stack);
|
||||
void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack);
|
||||
void *msan_valloc(uptr size, StackTrace *stack);
|
||||
void *msan_pvalloc(uptr size, StackTrace *stack);
|
||||
void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack);
|
||||
|
|
|
@ -261,6 +261,16 @@ void *msan_realloc(void *ptr, uptr size, StackTrace *stack) {
|
|||
return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64)));
|
||||
}
|
||||
|
||||
void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
|
||||
errno = errno_ENOMEM;
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
ReportReallocArrayOverflow(nmemb, size, stack);
|
||||
}
|
||||
return msan_realloc(ptr, nmemb * size, stack);
|
||||
}
|
||||
|
||||
void *msan_valloc(uptr size, StackTrace *stack) {
|
||||
return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false));
|
||||
}
|
||||
|
|
|
@ -907,6 +907,11 @@ INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
|
|||
return msan_realloc(ptr, size, &stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
|
||||
GET_MALLOC_STACK_TRACE;
|
||||
return msan_reallocarray(ptr, nmemb, size, &stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, malloc, SIZE_T size) {
|
||||
GET_MALLOC_STACK_TRACE;
|
||||
if (UNLIKELY(!msan_inited))
|
||||
|
@ -1597,6 +1602,7 @@ void InitializeInterceptors() {
|
|||
INTERCEPT_FUNCTION(malloc);
|
||||
INTERCEPT_FUNCTION(calloc);
|
||||
INTERCEPT_FUNCTION(realloc);
|
||||
INTERCEPT_FUNCTION(reallocarray);
|
||||
INTERCEPT_FUNCTION(free);
|
||||
MSAN_MAYBE_INTERCEPT_CFREE;
|
||||
MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
|
||||
|
|
|
@ -170,6 +170,18 @@ void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) {
|
|||
return (char*)p + sizeof(u64);
|
||||
}
|
||||
|
||||
void *InternalReallocArray(void *addr, uptr count, uptr size,
|
||||
InternalAllocatorCache *cache) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(count, size))) {
|
||||
Report(
|
||||
"FATAL: %s: reallocarray parameters overflow: count * size (%zd * %zd) "
|
||||
"cannot be represented in type size_t\n",
|
||||
SanitizerToolName, count, size);
|
||||
Die();
|
||||
}
|
||||
return InternalRealloc(addr, count * size, cache);
|
||||
}
|
||||
|
||||
void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(count, size))) {
|
||||
Report("FATAL: %s: calloc parameters overflow: count * size (%zd * %zd) "
|
||||
|
|
|
@ -48,7 +48,9 @@ void *InternalAlloc(uptr size, InternalAllocatorCache *cache = nullptr,
|
|||
uptr alignment = 0);
|
||||
void *InternalRealloc(void *p, uptr size,
|
||||
InternalAllocatorCache *cache = nullptr);
|
||||
void *InternalCalloc(uptr countr, uptr size,
|
||||
void *InternalReallocArray(void *p, uptr count, uptr size,
|
||||
InternalAllocatorCache *cache = nullptr);
|
||||
void *InternalCalloc(uptr count, uptr size,
|
||||
InternalAllocatorCache *cache = nullptr);
|
||||
void InternalFree(void *p, InternalAllocatorCache *cache = nullptr);
|
||||
InternalAllocator *internal_allocator();
|
||||
|
|
|
@ -51,6 +51,18 @@ void NORETURN ReportCallocOverflow(uptr count, uptr size,
|
|||
Die();
|
||||
}
|
||||
|
||||
void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
|
||||
const StackTrace *stack) {
|
||||
{
|
||||
ScopedAllocatorErrorReport report("reallocarray-overflow", stack);
|
||||
Report(
|
||||
"ERROR: %s: reallocarray parameters overflow: count * size (%zd * %zd) "
|
||||
"cannot be represented in type size_t\n",
|
||||
SanitizerToolName, count, size);
|
||||
}
|
||||
Die();
|
||||
}
|
||||
|
||||
void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack) {
|
||||
{
|
||||
ScopedAllocatorErrorReport report("pvalloc-overflow", stack);
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace __sanitizer {
|
|||
|
||||
void NORETURN ReportCallocOverflow(uptr count, uptr size,
|
||||
const StackTrace *stack);
|
||||
void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
|
||||
const StackTrace *stack);
|
||||
void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack);
|
||||
void NORETURN ReportInvalidAllocationAlignment(uptr alignment,
|
||||
const StackTrace *stack);
|
||||
|
|
|
@ -487,6 +487,7 @@
|
|||
#define SANITIZER_INTERCEPT_CFREE \
|
||||
(!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \
|
||||
SI_NOT_RTEMS)
|
||||
#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
|
||||
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_OPENBSD)
|
||||
#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
|
||||
|
|
|
@ -706,6 +706,19 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
|
|||
return p;
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
|
||||
if (in_symbolizer())
|
||||
return InternalReallocArray(p, size, n);
|
||||
if (p)
|
||||
invoke_free_hook(p);
|
||||
{
|
||||
SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);
|
||||
p = user_reallocarray(thr, pc, p, size, n);
|
||||
}
|
||||
invoke_malloc_hook(p, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(void, free, void *p) {
|
||||
if (p == 0)
|
||||
return;
|
||||
|
@ -2667,6 +2680,7 @@ void InitializeInterceptors() {
|
|||
TSAN_INTERCEPT(__libc_memalign);
|
||||
TSAN_INTERCEPT(calloc);
|
||||
TSAN_INTERCEPT(realloc);
|
||||
TSAN_INTERCEPT(reallocarray);
|
||||
TSAN_INTERCEPT(free);
|
||||
TSAN_INTERCEPT(cfree);
|
||||
TSAN_INTERCEPT(munmap);
|
||||
|
|
|
@ -201,6 +201,16 @@ void *user_calloc(ThreadState *thr, uptr pc, uptr size, uptr n) {
|
|||
return SetErrnoOnNull(p);
|
||||
}
|
||||
|
||||
void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {
|
||||
if (UNLIKELY(CheckForCallocOverflow(size, n))) {
|
||||
if (AllocatorMayReturnNull())
|
||||
return SetErrnoOnNull(nullptr);
|
||||
GET_STACK_TRACE_FATAL(thr, pc);
|
||||
ReportReallocArrayOverflow(size, n, &stack);
|
||||
}
|
||||
return user_realloc(thr, pc, p, size * n);
|
||||
}
|
||||
|
||||
void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
|
||||
DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
|
||||
ctx->metamap.AllocBlock(thr, pc, p, sz);
|
||||
|
|
|
@ -34,6 +34,7 @@ void user_free(ThreadState *thr, uptr pc, void *p, bool signal = true);
|
|||
void *user_alloc(ThreadState *thr, uptr pc, uptr sz);
|
||||
void *user_calloc(ThreadState *thr, uptr pc, uptr sz, uptr n);
|
||||
void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
|
||||
void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr sz, uptr n);
|
||||
void *user_memalign(ThreadState *thr, uptr pc, uptr align, uptr sz);
|
||||
int user_posix_memalign(ThreadState *thr, uptr pc, void **memptr, uptr align,
|
||||
uptr sz);
|
||||
|
|
|
@ -1,36 +1,43 @@
|
|||
// Test basic realloc functionality.
|
||||
// RUN: %clang_hwasan %s -o %t
|
||||
// RUN: %run %t
|
||||
// RUN: %clang_hwasan %s -o %t && %run %t
|
||||
// RUN: %clang_hwasan %s -DREALLOCARRAY -o %t && %run %t
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sanitizer/hwasan_interface.h>
|
||||
|
||||
#ifdef REALLOCARRAY
|
||||
extern "C" void *reallocarray(void *, size_t nmemb, size_t size);
|
||||
#define REALLOC(p, s) reallocarray(p, 1, s)
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define REALLOC(p, s) realloc(p, s)
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
__hwasan_enable_allocator_tagging();
|
||||
char *x = (char*)realloc(nullptr, 4);
|
||||
char *x = (char*)REALLOC(nullptr, 4);
|
||||
x[0] = 10;
|
||||
x[1] = 20;
|
||||
x[2] = 30;
|
||||
x[3] = 40;
|
||||
char *x1 = (char*)realloc(x, 5);
|
||||
char *x1 = (char*)REALLOC(x, 5);
|
||||
assert(x1 != x); // not necessary true for C,
|
||||
// but true today for hwasan.
|
||||
assert(x1[0] == 10 && x1[1] == 20 && x1[2] == 30 && x1[3] == 40);
|
||||
x1[4] = 50;
|
||||
|
||||
char *x2 = (char*)realloc(x1, 6);
|
||||
char *x2 = (char*)REALLOC(x1, 6);
|
||||
x2[5] = 60;
|
||||
assert(x2 != x1);
|
||||
assert(x2[0] == 10 && x2[1] == 20 && x2[2] == 30 && x2[3] == 40 &&
|
||||
x2[4] == 50 && x2[5] == 60);
|
||||
|
||||
char *x3 = (char*)realloc(x2, 6);
|
||||
char *x3 = (char*)REALLOC(x2, 6);
|
||||
assert(x3 != x2);
|
||||
assert(x3[0] == 10 && x3[1] == 20 && x3[2] == 30 && x3[3] == 40 &&
|
||||
x3[4] == 50 && x3[5] == 60);
|
||||
|
||||
char *x4 = (char*)realloc(x3, 5);
|
||||
char *x4 = (char*)REALLOC(x3, 5);
|
||||
assert(x4 != x3);
|
||||
assert(x4[0] == 10 && x4[1] == 20 && x4[2] == 30 && x4[3] == 40 &&
|
||||
x4[4] == 50);
|
||||
|
|
|
@ -20,6 +20,7 @@ int main() {
|
|||
sink = (void *)&__sanitizer_malloc_stats;
|
||||
sink = (void *)&__sanitizer_calloc;
|
||||
sink = (void *)&__sanitizer_realloc;
|
||||
sink = (void *)&__sanitizer_reallocarray;
|
||||
sink = (void *)&__sanitizer_malloc;
|
||||
|
||||
// sanity check
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t malloc max 2>&1
|
||||
// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-calloc
|
||||
// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t calloc 2>&1
|
||||
// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t reallocarray 2>&1 | FileCheck %s --check-prefix=CHECK-reallocarray
|
||||
// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t reallocarray 2>&1
|
||||
// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-max
|
||||
// RUN: %env_hwasan_opts=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-oom
|
||||
// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new max 2>&1 | FileCheck %s --check-prefix=CHECK-max
|
||||
|
@ -30,6 +32,7 @@
|
|||
#include <new>
|
||||
|
||||
#include <sanitizer/allocator_interface.h>
|
||||
#include <sanitizer/hwasan_interface.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
assert(argc <= 3);
|
||||
|
@ -51,6 +54,11 @@ int main(int argc, char **argv) {
|
|||
size_t size = std::numeric_limits<size_t>::max();
|
||||
void *p = calloc((size / 0x1000) + 1, 0x1000);
|
||||
assert(!p);
|
||||
} else if (!strcmp(argv[1], "reallocarray")) {
|
||||
// Trigger an overflow in reallocarray.
|
||||
size_t size = std::numeric_limits<size_t>::max();
|
||||
void *p = __sanitizer_reallocarray(nullptr, (size / 0x1000) + 1, 0x1000);
|
||||
assert(!p);
|
||||
} else if (!strcmp(argv[1], "new")) {
|
||||
void *p = operator new(MallocSize);
|
||||
assert(!p);
|
||||
|
@ -80,3 +88,4 @@ int main(int argc, char **argv) {
|
|||
// CHECK-max: {{ERROR: HWAddressSanitizer: requested allocation size .* exceeds maximum supported size}}
|
||||
// CHECK-oom: ERROR: HWAddressSanitizer: allocator is out of memory
|
||||
// CHECK-calloc: ERROR: HWAddressSanitizer: calloc parameters overflow
|
||||
// CHECK-reallocarray: ERROR: HWAddressSanitizer: reallocarray parameters overflow
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// RUN: %clangxx -O0 %s -o %t
|
||||
// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
|
||||
|
||||
// REQUIRES: stable-runtime && !ubsan && !darwin
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C" void *reallocarray(void *, size_t, size_t);
|
||||
|
||||
int main() {
|
||||
void *p = reallocarray(nullptr, -1, 1000);
|
||||
// CHECK: {{ERROR: .*Sanitizer: reallocarray parameters overflow: count \* size \(.* \* 1000\) cannot be represented in type size_t}}
|
||||
|
||||
printf("reallocarray returned: %zu\n", (size_t)p);
|
||||
// CHECK-NULL: reallocarray returned: 0
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue