From 5b133ca67da244d12c63e491fb79370ddcb387a8 Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Mon, 13 Jul 2026 11:48:52 +0100 Subject: [PATCH 3/4] xmalloc: avoid using reallocarray(3) to implement xreallocarray() See the added comment for reasoning. The reallocarray(3) function in libc could have been used conditionally, when available, but since it can be implemented simply and efficiently, the portable version may just as well be used in all cases. See also: * https://pubs.opengroup.org/onlinepubs/9799919799/functions/reallocarray.html#:~:text=adding-,reallocarray * https://android.googlesource.com/platform/bionic/+/HEAD/docs/status.md#:~:text=reallocarray * https://github.com/termux/termux-packages/tree/26826aec834182c/x11-packages/foot * https://github.com/termux/termux-packages/blob/26826aec834182c/x11-packages/foot/reallocarray.c#L6 * https://github.com/termux/termux-packages/blob/26826aec834182c/x11-packages/foot/xmalloc.c.patch#L7 * https://github.com/termux/termux-packages/pull/17818 * https://github.com/termux/termux-packages/issues/23833 (see expanded build log) --- debug.h | 3 ++- xmalloc.c | 15 +++++++++------ xmalloc.h | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/debug.h b/debug.h index 92a0e091..29ff9606 100644 --- a/debug.h +++ b/debug.h @@ -2,7 +2,8 @@ #include "macros.h" -#define FATAL_ERROR(...) fatal_error(__FILE__, __LINE__, __VA_ARGS__) +#define FATAL_ERROR(msg, err) fatal_error(__FILE__, __LINE__, msg, err) +#define FATAL_ERROR_ON(cond, err) if (unlikely(cond)) FATAL_ERROR(__func__, err) #ifdef NDEBUG #define BUG(...) UNREACHABLE() diff --git a/xmalloc.c b/xmalloc.c index ccfb5c48..e7693d3a 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "xmalloc.h" @@ -33,16 +34,18 @@ void * xrealloc(void *ptr, size_t size) { xassert(size != 0); - void *alloc = realloc(ptr, size); - return check_alloc(alloc); + return check_alloc(realloc(ptr, size)); } +// reallocarray(3) was only added to POSIX in Issue 8 (2024) and isn't +// present on some platforms (e.g. Android API levels < 29), so this +// function is both for portability and ENOMEM handling. void * -xreallocarray(void *ptr, size_t n, size_t size) +xreallocarray(void *ptr, size_t nmemb, size_t size) { - xassert(n != 0 && size != 0); - void *alloc = reallocarray(ptr, n, size); - return check_alloc(alloc); + FATAL_ERROR_ON(nmemb == 0 || size == 0, EINVAL); + FATAL_ERROR_ON(size > SIZE_MAX / nmemb, EOVERFLOW); + return xrealloc(ptr, nmemb * size); } char * diff --git a/xmalloc.h b/xmalloc.h index 03e6eb0d..33a17ca5 100644 --- a/xmalloc.h +++ b/xmalloc.h @@ -12,7 +12,7 @@ void *xmalloc(size_t size) XMALLOC; void *xcalloc(size_t nmemb, size_t size) XMALLOC; void *xrealloc(void *ptr, size_t size); -void *xreallocarray(void *ptr, size_t n, size_t size); +void *xreallocarray(void *ptr, size_t nmemb, size_t size); char *xstrdup(const char *str) XSTRDUP; char *xstrndup(const char *str, size_t n) XSTRDUP; char *xasprintf(const char *format, ...) PRINTF(1) XMALLOC; -- 2.43.0