Merge "Disable STL for crt objects"
diff --git a/docs/status.md b/docs/status.md
index b6439a0..0106ccd 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -39,6 +39,7 @@
 
 New libc functions in Q (API level 29):
   * `timespec_get` (C11 `<time.h>` addition)
+  * `reallocarray` (BSD/GNU extension in `<malloc.h>` and `<stdlib.h>`)
   * `res_randomid` (in `<resolv.h>`)
   * `pthread_sigqueue` (GNU extension)
 
diff --git a/libc/Android.bp b/libc/Android.bp
index ed8548a..cc0a2bb 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);
diff --git a/libm/Android.bp b/libm/Android.bp
index 3b88fa3..6d55967 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -290,13 +290,9 @@
 
         arm64: {
             srcs: [
-                "arm64/ceil.S",
                 "arm64/fenv.c",
-                "arm64/floor.S",
                 "arm64/lrint.S",
-                "arm64/rint.S",
                 "arm64/sqrt.S",
-                "arm64/trunc.S",
             ],
             exclude_srcs: [
                 "upstream-freebsd/lib/msun/src/e_sqrt.c",
diff --git a/libm/arm64/ceil.S b/libm/arm64/ceil.S
deleted file mode 100644
index 7217d57..0000000
--- a/libm/arm64/ceil.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY(ceil)
-  frintP d0, d0
-  ret
-END(ceil)
-
-ENTRY(ceilf)
-  frintP s0, s0
-  ret
-END(ceilf)
diff --git a/libm/arm64/floor.S b/libm/arm64/floor.S
deleted file mode 100644
index ca106bd..0000000
--- a/libm/arm64/floor.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY(floor)
-  frintM d0, d0
-  ret
-END(floor)
-
-ENTRY(floorf)
-  frintM s0, s0
-  ret
-END(floorf)
diff --git a/libm/arm64/rint.S b/libm/arm64/rint.S
deleted file mode 100644
index bf49f5b..0000000
--- a/libm/arm64/rint.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY(rint)
-  frintX d0, d0
-  ret
-END(rint)
-
-ENTRY(rintf)
-  frintX s0, s0
-  ret
-END(rintf)
diff --git a/libm/arm64/trunc.S b/libm/arm64/trunc.S
deleted file mode 100644
index aa0d4bd..0000000
--- a/libm/arm64/trunc.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY(trunc)
-  frintZ d0, d0
-  ret
-END(trunc)
-
-ENTRY(truncf)
-  frintZ s0, s0
-  ret
-END(truncf)
diff --git a/libm/builtins.cpp b/libm/builtins.cpp
index 2ea6305..3b9228c 100644
--- a/libm/builtins.cpp
+++ b/libm/builtins.cpp
@@ -46,6 +46,12 @@
 #endif
 
 #if defined(__aarch64__)
+float ceilf(float x) { return __builtin_ceilf(x); }
+double ceil(double x) { return __builtin_ceil(x); }
+
+float floorf(float x) { return __builtin_floorf(x); }
+double floor(double x) { return __builtin_floor(x); }
+
 float fmaf(float x, float y, float z) { return __builtin_fmaf(x, y, z); }
 double fma(double x, double y, double z) { return __builtin_fma(x, y, z); }
 
@@ -55,6 +61,12 @@
 float fminf(float x, float y) { return __builtin_fminf(x, y); }
 double fmin(double x, double y) { return __builtin_fmin(x, y); }
 
+float rintf(float x) { return __builtin_rintf(x); }
+double rint(double x) { return __builtin_rint(x); }
+
 float roundf(float x) { return __builtin_roundf(x); }
 double round(double x) { return __builtin_round(x); }
+
+float truncf(float x) { return __builtin_truncf(x); }
+double trunc(double x) { return __builtin_trunc(x); }
 #endif
diff --git a/linker/linker_memory.cpp b/linker/linker_memory.cpp
index 6a54c13..f2cce01 100644
--- a/linker/linker_memory.cpp
+++ b/linker/linker_memory.cpp
@@ -80,7 +80,15 @@
   return get_allocator().realloc(p, byte_count);
 }
 
+void* reallocarray(void* p, size_t item_count, size_t item_size) {
+  size_t byte_count;
+  if (__builtin_mul_overflow(item_count, item_size, &byte_count)) {
+    errno = ENOMEM;
+    return nullptr;
+  }
+  return get_allocator().realloc(p, byte_count);
+}
+
 void free(void* ptr) {
   get_allocator().free(ptr);
 }
-
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 4161c90..c4f13f6 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -26,6 +26,12 @@
 
 #include "private/bionic_config.h"
 
+#if defined(__BIONIC__)
+#define HAVE_REALLOCARRAY 1
+#else
+#define HAVE_REALLOCARRAY __GLIBC_PREREQ(2, 26)
+#endif
+
 TEST(malloc, malloc_std) {
   // Simple malloc test.
   void *ptr = malloc(100);
@@ -497,3 +503,31 @@
   // mallopt doesn't set errno.
   ASSERT_EQ(0, errno);
 }
+
+TEST(malloc, reallocarray_overflow) {
+#if HAVE_REALLOCARRAY
+  // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
+  size_t a = static_cast<size_t>(INTPTR_MIN + 4);
+  size_t b = 2;
+
+  errno = 0;
+  ASSERT_TRUE(reallocarray(nullptr, a, b) == nullptr);
+  ASSERT_EQ(ENOMEM, errno);
+
+  errno = 0;
+  ASSERT_TRUE(reallocarray(nullptr, b, a) == nullptr);
+  ASSERT_EQ(ENOMEM, errno);
+#else
+  GTEST_LOG_(INFO) << "This test requires a C library with reallocarray.\n";
+#endif
+}
+
+TEST(malloc, reallocarray) {
+#if HAVE_REALLOCARRAY
+  void* p = reallocarray(nullptr, 2, 32);
+  ASSERT_TRUE(p != nullptr);
+  ASSERT_GE(malloc_usable_size(p), 64U);
+#else
+  GTEST_LOG_(INFO) << "This test requires a C library with reallocarray.\n";
+#endif
+}