Add reallocarray(3).
Originally a BSD extension, now in glibc too. We've used it internally
for a while.
(cherry-pick of e4b13f7e3ca68edfcc5faedc5e7d4e13c4e8edb9.)
Bug: http://b/112163459
Test: ran tests
Change-Id: I813c3a62b13ddb91ba41e32a5a853d09207ea6bc
Merged-In: I813c3a62b13ddb91ba41e32a5a853d09207ea6bc
diff --git a/libc/Android.bp b/libc/Android.bp
index 57173d1..7dee589 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -479,7 +479,6 @@
"upstream-openbsd/lib/libc/stdlib/labs.c",
"upstream-openbsd/lib/libc/stdlib/llabs.c",
"upstream-openbsd/lib/libc/stdlib/lsearch.c",
- "upstream-openbsd/lib/libc/stdlib/reallocarray.c",
"upstream-openbsd/lib/libc/stdlib/remque.c",
"upstream-openbsd/lib/libc/stdlib/setenv.c",
"upstream-openbsd/lib/libc/stdlib/tfind.c",
diff --git a/libc/NOTICE b/libc/NOTICE
index 486c615..5cce4d4 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -4738,22 +4738,6 @@
-------------------------------------------------------------------
-Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
Permission to use, copy, modify, and distribute this software for any
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 5a5ec76..8bf44a1 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -184,6 +184,15 @@
return Malloc(realloc)(old_mem, bytes);
}
+extern "C" void* reallocarray(void* old_mem, size_t item_count, size_t item_size) {
+ size_t new_size;
+ if (__builtin_mul_overflow(item_count, item_size, &new_size)) {
+ errno = ENOMEM;
+ return nullptr;
+ }
+ return realloc(old_mem, new_size);
+}
+
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
extern "C" void* pvalloc(size_t bytes) {
auto _pvalloc = __libc_globals->malloc_dispatch.pvalloc;
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 7144224..f5fbedf 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -66,6 +66,18 @@
void* realloc(void* __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
/**
+ * [reallocarray(3)](http://man7.org/linux/man-pages/man3/realloc.3.html) resizes
+ * allocated memory on the heap.
+ *
+ * Equivalent to `realloc(__ptr, __item_count * __item_size)` but fails if the
+ * multiplication overflows.
+ *
+ * Returns a pointer (which may be different from `__ptr`) to the resized
+ * memory on success and returns a null pointer and sets `errno` on failure.
+ */
+void* reallocarray(void* __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
+
+/**
* [free(3)](http://man7.org/linux/man-pages/man3/free.3.html) deallocates
* memory on the heap.
*/
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 2891925..a22a8df 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1433,6 +1433,7 @@
android_fdsan_set_error_level;
android_get_device_api_level;
pthread_sigqueue;
+ reallocarray;
timespec_get;
} LIBC_P;
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 3e8cea2..55fd587 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1354,6 +1354,7 @@
android_fdsan_set_error_level;
android_get_device_api_level;
pthread_sigqueue;
+ reallocarray;
timespec_get;
} LIBC_P;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 2770f21..304dbb7 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1458,6 +1458,7 @@
android_fdsan_set_error_level;
android_get_device_api_level;
pthread_sigqueue;
+ reallocarray;
timespec_get;
} LIBC_P;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 456e35c..397ff72 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1417,6 +1417,7 @@
android_fdsan_set_error_level;
android_get_device_api_level;
pthread_sigqueue;
+ reallocarray;
timespec_get;
} LIBC_P;
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 3e8cea2..55fd587 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1354,6 +1354,7 @@
android_fdsan_set_error_level;
android_get_device_api_level;
pthread_sigqueue;
+ reallocarray;
timespec_get;
} LIBC_P;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 4cbef13..a18657c 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1415,6 +1415,7 @@
android_fdsan_set_error_level;
android_get_device_api_level;
pthread_sigqueue;
+ reallocarray;
timespec_get;
} LIBC_P;
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 3e8cea2..55fd587 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1354,6 +1354,7 @@
android_fdsan_set_error_level;
android_get_device_api_level;
pthread_sigqueue;
+ reallocarray;
timespec_get;
} LIBC_P;
diff --git a/libc/upstream-freebsd/android/include/freebsd-compat.h b/libc/upstream-freebsd/android/include/freebsd-compat.h
index e646e23..6f7a3f0 100644
--- a/libc/upstream-freebsd/android/include/freebsd-compat.h
+++ b/libc/upstream-freebsd/android/include/freebsd-compat.h
@@ -44,9 +44,6 @@
/* Redirect internal C library calls to the public function. */
#define _nanosleep nanosleep
-/* FreeBSD has this as API, but we just use it internally. */
-void* reallocarray(void*, size_t, size_t);
-
/* FreeBSD has this, but we can't really implement it correctly on Linux. */
#define issetugid() 0
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index f178149..c99e2ce 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -80,9 +80,6 @@
__LIBC_HIDDEN__ extern const char* __bionic_get_shell_path();
#define _PATH_BSHELL __bionic_get_shell_path()
-/* OpenBSD has this as API, but we just use it internally. */
-__LIBC_HIDDEN__ void* reallocarray(void*, size_t, size_t);
-
/* LP32 NDK ctype.h contained references to these. */
__LIBC32_LEGACY_PUBLIC__ extern const short* _tolower_tab_;
__LIBC32_LEGACY_PUBLIC__ extern const short* _toupper_tab_;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c b/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c
deleted file mode 100644
index baea252..0000000
--- a/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $ */
-/*
- * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-/*
- * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
- * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
- */
-#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
-
-void *
-reallocarray(void *optr, size_t nmemb, size_t size)
-{
- if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
- nmemb > 0 && SIZE_MAX / nmemb < size) {
- errno = ENOMEM;
- return NULL;
- }
- return realloc(optr, size * nmemb);
-}
-DEF_WEAK(reallocarray);