[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:
Evgeniy Stepanov 2019-05-01 17:33:01 +00:00
parent 9f04d97cd7
commit d1a710047b
30 changed files with 215 additions and 9 deletions

View File

@ -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"

View File

@ -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));

View File

@ -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);

View File

@ -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());

View File

@ -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) \

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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));
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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));
}

View File

@ -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;

View File

@ -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) "

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}