public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add reallocarray function.
@ 2017-04-10 15:01 Dennis Wölfing
  2017-04-10 15:18 ` Zack Weinberg
                   ` (3 more replies)
  0 siblings, 4 replies; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-10 15:01 UTC (permalink / raw)
  To: libc-alpha

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on x86_64-linux.

2017-04-10  Dennis Wölfing  <denniswoelfing@gmx.de>

	* malloc/malloc.c (check_mul_overflow): Use
	__builtin_mul_overflow if available.
	* stdlib/stdlib.h (reallocarray): Declare only for __USE_GNU.
	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

2017-04-10  Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* malloc/Versions: Add reallocarray and __libc_rallocarray.
	* malloc/Makefile (tests): Add tst-reallocarray.c.
	* malloc/tst-reallocarray.c: New test file.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/malloc.c (check_mul_overflow): New inline function.
	(__libc_reallocarray): New function.
	(__libc_calloc): Use `check_mul_overflow'.
---
 malloc/Makefile                                    |   2 +-
 malloc/Versions                                    |   4 +
 malloc/malloc.c                                    |  48 +++++--
 malloc/malloc.h                                    |   8 ++
 malloc/tst-reallocarray.c                          | 160 +++++++++++++++++++++
 stdlib/stdlib.h                                    |  11 ++
 sysdeps/arm/nacl/libc.abilist                      |   3 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   3 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   3 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   3 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   3 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   3 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   3 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   3 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   3 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   3 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   3 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   3 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   3 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   3 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   3 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   3 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   3 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   3 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   3 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   3 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   3 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   3 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   3 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   3 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   3 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   3 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   3 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   3 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   3 +
 35 files changed, 309 insertions(+), 11 deletions(-)
 create mode 100644 malloc/tst-reallocarray.c

diff --git a/malloc/Makefile b/malloc/Makefile
index e93b83b57d..b1466ed815 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
diff --git a/malloc/Versions b/malloc/Versions
index f3c3d8a093..299b139e7d 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -61,6 +61,10 @@ libc {
   GLIBC_2.16 {
     aligned_alloc;
   }
+  GLIBC_2.26 {
+    __libc_reallocarray;
+    reallocarray;
+  }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
     __libc_malloc_pthread_startup;
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 4c40e2ea19..ca22e53f63 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2950,6 +2950,39 @@ __libc_free (void *mem)
 }
 libc_hidden_def (__libc_free)
 
+static inline bool
+check_mul_overflow(size_t l, size_t r, INTERNAL_SIZE_T *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow(l, r, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = l * r;
+# define HALF_INTERNAL_SIZE_T                                   \
+  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
+  if (__glibc_unlikely ((l | r) >= HALF_INTERNAL_SIZE_T))
+    {
+      if (r != 0 && *result / r != l)
+        return true;
+    }
+  return false;
+# undef HALF_INTERNAL_SIZE_T
+#endif
+}
+
+void *
+__libc_reallocarray(void *optr, size_t nmemb, size_t elem_size)
+{
+  INTERNAL_SIZE_T bytes;
+  if (check_mul_overflow(nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return __libc_realloc (optr, bytes);
+}
+
 void *
 __libc_realloc (void *oldmem, size_t bytes)
 {
@@ -3180,17 +3213,10 @@ __libc_calloc (size_t n, size_t elem_size)
   unsigned long nclears;
   INTERNAL_SIZE_T *d;
 
-  /* size_t is unsigned so the behavior on overflow is defined.  */
-  bytes = n * elem_size;
-#define HALF_INTERNAL_SIZE_T \
-  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
-  if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0))
+  if (check_mul_overflow(n, elem_size, &bytes))
     {
-      if (elem_size != 0 && bytes / elem_size != n)
-        {
-          __set_errno (ENOMEM);
-          return 0;
-        }
+      __set_errno (ENOMEM);
+      return 0;
     }
 
   void *(*hook) (size_t, const void *) =
@@ -5295,6 +5321,8 @@ strong_alias (__libc_free, __free) strong_alias (__libc_free, free)
 strong_alias (__libc_malloc, __malloc) strong_alias (__libc_malloc, malloc)
 strong_alias (__libc_memalign, __memalign)
 weak_alias (__libc_memalign, memalign)
+strong_alias (__libc_reallocarray, __reallocarray)
+weak_alias (__libc_reallocarray, reallocarray)
 strong_alias (__libc_realloc, __realloc) strong_alias (__libc_realloc, realloc)
 strong_alias (__libc_valloc, __valloc) weak_alias (__libc_valloc, valloc)
 strong_alias (__libc_pvalloc, __pvalloc) weak_alias (__libc_pvalloc, pvalloc)
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 0bd8f97bc3..5ddc97b511 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..3c3e2e49a5
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+  ++errors;
+  printf ("Error: %s.\n", msg);
+}
+
+static int
+do_test (void)
+
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  if (ptr)
+    {
+      merror ("Overflow for size_t MAX * 2 not detected");
+      free(ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  if (ptr)
+    {
+      merror ("Overflow for 2 * size_t MAX not detected");
+      free(ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  if (ptr)
+    {
+      merror ("Overflow for (size_t MAX/65537 + 1) * 65537 not detected");
+      free(ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  if (ptr)
+    {
+      merror ("Overflow for 65537 * (size_t MAX/65537 + 1)  not detected");
+      free(ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray(NULL, 10, 2);
+  if (!ptr)
+    merror ("realloc(NULL, 10, 2) failed");
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray(ptr, 20, 2);
+  if (!ptr2)
+    merror ("realloc(ptr, 20, 2) failed (enlarge)");
+  else
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Enlarging changed buffer content (10*2)");
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray(ptr, 5, 3);
+  if (!ptr2)
+    merror ("realloc(ptr, 5, 3) failed (decrease)");
+  else
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Reducing changed buffer content (5*3)");
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray(ptr, 2, ~(size_t)0);
+  if (ptr2)
+    merror ("realloc(ptr, 2, size_t MAX) failed to detect overflow");
+  if (errno != ENOMEM)
+    merror ("errno not set correctly");
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Overflow changed buffer content (5*3)");
+
+  /* Free buffer (glibc).  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 0, 0);
+  if (ptr2)
+    merror ("reallocarray (ptr, 0, 0) returned non-NULL");
+
+  free (ptr2);
+
+  return errors != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index c1f389253a..dad94dcc74 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index abd70c8108..d20e15939d 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1853,3 +1853,6 @@ GLIBC_2.25 gnu_dev_minor F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..63a17e749a 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..73ae8df289 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..5657618fd8 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..3f391ac381 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..ba2d7fb0b5 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..f183c2b650 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..1c67ad8f64 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..9a3b9fb5b4 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..e9eacf089e 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..8cc32f3b70 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..f485aa523f 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..c0154d577a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..5221e90d14 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..d566c08a0d 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..0056e5d1f6 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..7eb7f2838c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..95090e3269 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..114ae98ca9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..e40a24a05e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..1c3d6bfb40 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..7aa485964e 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..d399105810 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..235a130e1b 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..e62db6d3be 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..3d727c01cb 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..e62db6d3be 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..80f66bd37e 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,9 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..8619685113 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,6 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __libc_reallocarray F
+GLIBC_2.26 reallocarray F
-- 
2.12.2

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-10 15:01 [PATCH] Add reallocarray function Dennis Wölfing
@ 2017-04-10 15:18 ` Zack Weinberg
  2017-04-10 18:27   ` Dennis Wölfing
  2017-04-10 16:03 ` Andreas Schwab
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 48+ messages in thread
From: Zack Weinberg @ 2017-04-10 15:18 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: GNU C Library

On Mon, Apr 10, 2017 at 11:00 AM, Dennis Wölfing <denniswoelfing@gmx.de> wrote:
> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
>
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

I agree in principle with adding this function.  I skimmed the patch
and it seems to be mostly the Right Thing.  I do have two concerns:

* There do not appear to be any uses of the internal aliases
__libc_reallocarray and __reallocarray.  Have you audited glibc itself
for places that should use reallocarray?  If you haven't, would you be
willing to do that?  This will determine whether we actually need
those aliases.

* Please add documentation for reallocarray.  It belongs in
manual/memory.texi, in the "Changing Block Size" section.  This is the
place to explain when and why one should use reallocarray instead of
realloc.

zw

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-10 15:01 [PATCH] Add reallocarray function Dennis Wölfing
  2017-04-10 15:18 ` Zack Weinberg
@ 2017-04-10 16:03 ` Andreas Schwab
  2017-04-11  7:55 ` Florian Weimer
  2017-04-17 14:02 ` [PATCH v2] " Dennis Wölfing
  3 siblings, 0 replies; 48+ messages in thread
From: Andreas Schwab @ 2017-04-10 16:03 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha

On Apr 10 2017, Dennis Wölfing <denniswoelfing@gmx.de> wrote:

> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 4c40e2ea19..ca22e53f63 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -2950,6 +2950,39 @@ __libc_free (void *mem)
>  }
>  libc_hidden_def (__libc_free)
>  
> +static inline bool
> +check_mul_overflow(size_t l, size_t r, INTERNAL_SIZE_T *result)
> +{
> +#if __GNUC__ >= 5
> +  return __builtin_mul_overflow(l, r, result);
> +#else
> +  /* size_t is unsigned so the behavior on overflow is defined.  */
> +  *result = l * r;
> +# define HALF_INTERNAL_SIZE_T                                   \
> +  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
> +  if (__glibc_unlikely ((l | r) >= HALF_INTERNAL_SIZE_T))
> +    {
> +      if (r != 0 && *result / r != l)
> +        return true;
> +    }
> +  return false;
> +# undef HALF_INTERNAL_SIZE_T
> +#endif
> +}
> +
> +void *
> +__libc_reallocarray(void *optr, size_t nmemb, size_t elem_size)
> +{
> +  INTERNAL_SIZE_T bytes;
> +  if (check_mul_overflow(nmemb, elem_size, &bytes))
> +    {
> +      __set_errno (ENOMEM);
> +      return 0;
> +    }
> +  else
> +    return __libc_realloc (optr, bytes);
> +}
> +

Style: please put a space before paren on function calls.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-10 15:18 ` Zack Weinberg
@ 2017-04-10 18:27   ` Dennis Wölfing
  2017-04-16 13:19     ` Dennis Wölfing
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-10 18:27 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

On 10.04.2017 17:18, Zack Weinberg wrote:
> On Mon, Apr 10, 2017 at 11:00 AM, Dennis Wölfing <denniswoelfing@gmx.de> wrote:
>> The reallocarray function is an extension from OpenBSD.  It is an
>> integer-overflow-safe replacement for realloc(p, X*Y) and
>> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
>> certain security issues in code.
>>
>> This is an updated version of a patch originally submitted by Rüdiger
>> Sonderfeld in May 2014.
>> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
> 
> I agree in principle with adding this function.  I skimmed the patch
> and it seems to be mostly the Right Thing.  I do have two concerns:
> 
> * There do not appear to be any uses of the internal aliases
> __libc_reallocarray and __reallocarray.  Have you audited glibc itself
> for places that should use reallocarray?  If you haven't, would you be
> willing to do that?  This will determine whether we actually need
> those aliases.

I have not yet checked where glibc itself should use reallocarray but I
will do so.

> * Please add documentation for reallocarray.  It belongs in
> manual/memory.texi, in the "Changing Block Size" section.  This is the
> place to explain when and why one should use reallocarray instead of
> realloc.

Ok, I will look into this.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-10 15:01 [PATCH] Add reallocarray function Dennis Wölfing
  2017-04-10 15:18 ` Zack Weinberg
  2017-04-10 16:03 ` Andreas Schwab
@ 2017-04-11  7:55 ` Florian Weimer
  2017-04-12 15:24   ` Dennis Wölfing
  2017-04-17 14:02 ` [PATCH v2] " Dennis Wölfing
  3 siblings, 1 reply; 48+ messages in thread
From: Florian Weimer @ 2017-04-11  7:55 UTC (permalink / raw)
  To: Dennis Wölfing, libc-alpha

On 04/10/2017 05:00 PM, Dennis Wölfing wrote:
> +void *
> +__libc_reallocarray(void *optr, size_t nmemb, size_t elem_size)
> +{
> +  INTERNAL_SIZE_T bytes;
> +  if (check_mul_overflow(nmemb, elem_size, &bytes))
> +    {
> +      __set_errno (ENOMEM);
> +      return 0;
> +    }
> +  else
> +    return __libc_realloc (optr, bytes);
> +}

This needs to go into its own file and has to call realloc (not 
__libc_realloc), otherwise it will not be compatible with malloc 
interposition.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-11  7:55 ` Florian Weimer
@ 2017-04-12 15:24   ` Dennis Wölfing
  2017-04-12 16:35     ` Florian Weimer
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-12 15:24 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 11.04.2017 09:55, Florian Weimer wrote:
> On 04/10/2017 05:00 PM, Dennis Wölfing wrote:
>> +void *
>> +__libc_reallocarray(void *optr, size_t nmemb, size_t elem_size)
>> +{
>> +  INTERNAL_SIZE_T bytes;
>> +  if (check_mul_overflow(nmemb, elem_size, &bytes))
>> +    {
>> +      __set_errno (ENOMEM);
>> +      return 0;
>> +    }
>> +  else
>> +    return __libc_realloc (optr, bytes);
>> +}
> 
> This needs to go into its own file and has to call realloc (not
> __libc_realloc), otherwise it will not be compatible with malloc
> interposition.

Ok, I see the problem. When a statically linked program defines their
own memory allocation functions, calls to reallocarray pull in malloc.c
and thus cause link errors.

The static inline function check_mul_overflow is used in both
reallocarray and calloc. So that function would need to be in a file
that can be included by both malloc.c and a new reallocarray.c file.

Would malloc-internal.h be a good location to put that inline function
or should I place it into its own separate file?

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-12 15:24   ` Dennis Wölfing
@ 2017-04-12 16:35     ` Florian Weimer
  0 siblings, 0 replies; 48+ messages in thread
From: Florian Weimer @ 2017-04-12 16:35 UTC (permalink / raw)
  To: Dennis Wölfing, libc-alpha

On 04/12/2017 05:24 PM, Dennis Wölfing wrote:

> The static inline function check_mul_overflow is used in both
> reallocarray and calloc. So that function would need to be in a file
> that can be included by both malloc.c and a new reallocarray.c file.
> 
> Would malloc-internal.h be a good location to put that inline function
> or should I place it into its own separate file?

Use malloc-internal.h or create a new malloc-private.h header. 
malloc-internal.h is used for things which are used in other glibc 
modules (fork handler and ld.so), but we aren't fully consistent yet 
about the distinction in other areas of the library.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-10 18:27   ` Dennis Wölfing
@ 2017-04-16 13:19     ` Dennis Wölfing
  2017-04-16 13:38       ` Florian Weimer
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-16 13:19 UTC (permalink / raw)
  To: Zack Weinberg, GNU C Library

On 10.04.2017 20:26, Dennis Wölfing wrote:
> On 10.04.2017 17:18, Zack Weinberg wrote:
>> On Mon, Apr 10, 2017 at 11:00 AM, Dennis Wölfing <denniswoelfing@gmx.de> wrote:
>>> The reallocarray function is an extension from OpenBSD.  It is an
>>> integer-overflow-safe replacement for realloc(p, X*Y) and
>>> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
>>> certain security issues in code.
>>>
>>> This is an updated version of a patch originally submitted by Rüdiger
>>> Sonderfeld in May 2014.
>>> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
>>
>> I agree in principle with adding this function.  I skimmed the patch
>> and it seems to be mostly the Right Thing.  I do have two concerns:
>>
>> * There do not appear to be any uses of the internal aliases
>> __libc_reallocarray and __reallocarray.  Have you audited glibc itself
>> for places that should use reallocarray?  If you haven't, would you be
>> willing to do that?  This will determine whether we actually need
>> those aliases.
> 
> I have not yet checked where glibc itself should use reallocarray but I
> will do so.

At least the following files contain calls to realloc where the size
argument is the result of a multiplication. Note that I have not checked
all of these files in detail so it is possible that many these
multiplications can never overflow.

catgets/gencat.c
dirent/scandir-tail.c
grp/compat-initgroups.c
hesiod/nss_hesiod/hesiod-grp.c
iconv/iconvconfig.c
io/fts.c
libidn/idna.c
libio/iogetdelim.c
locale/programs/3level.h
locale/programs/charmap-dir.c
locale/programs/ld-collate.c
locale/programs/ld-ctypes.c
locale/programs/ld-monetary.c
locale/programs/ld-numeric.c
locale/programs/ld-time.c
locale/programs/locfile.c
misc/err.c
misc/error.c
nis/nis_addmember.c
nis/nis_call.c
nis/nis_findserv.c
nis/nis_subr.c
nis/nis_table.c
nis/nss_compat/compat-initgroups.c
nis/nss_nis/nis_initgroups.c
nis/nss_nisplus/nisplus-initgroups.c
nscd/grpcache.c
nscd/hstcache.c
nscd/nscd_initgroups.c
nscd/pwdcache.c
nscd/servicescache.c
nss/getXXbyYY.c
nss/getnssent.c
posix/glob.c
resolv/gai_misc.c
resolv/res_hconf.c

Perhaps some of them should use reallocarray to detect overflows. So I
guess these internal aliases should be fine.

But another question occurred to me: Should __libc_reallocarray be
listed in malloc/Versions and the abilist files? I would guess no
because this name should only be used internally, but most other memory
allocation functions do have their __libc_ prefixed name listed as part
of the public abi.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] Add reallocarray function.
  2017-04-16 13:19     ` Dennis Wölfing
@ 2017-04-16 13:38       ` Florian Weimer
  0 siblings, 0 replies; 48+ messages in thread
From: Florian Weimer @ 2017-04-16 13:38 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: Zack Weinberg, GNU C Library

* Dennis Wölfing:

> But another question occurred to me: Should __libc_reallocarray be
> listed in malloc/Versions and the abilist files?

It has to be listed under GLIBC_PRIVATE because otherwise, code
outside of libc.so proper (such as nss_nis) would not be able to call
it.  Separate programs such as nscd can directly call reallocarray.

> I would guess no because this name should only be used internally,
> but most other memory allocation functions do have their __libc_
> prefixed name listed as part of the public abi.

That's more or less a historical accident.  The dynamic linker used
memalign internally, but calling it under this name would result in a
namespace violation, so it uses __libc_memalign instead.  This symbol
was made part of the public ABI so that external mallocs can interpose
it (although interposition would have worked just fine for a
GLIBC_PRIVATE symbol, too).  I assume some of the other __libc_*
aliases were just added for consistency.  Today, this is just historic
cruft, which we could replace with compat symbols.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v2] Add reallocarray function.
  2017-04-10 15:01 [PATCH] Add reallocarray function Dennis Wölfing
                   ` (2 preceding siblings ...)
  2017-04-11  7:55 ` Florian Weimer
@ 2017-04-17 14:02 ` Dennis Wölfing
  2017-04-17 14:32   ` Florian Weimer
                     ` (3 more replies)
  3 siblings, 4 replies; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-17 14:02 UTC (permalink / raw)
  To: libc-alpha

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on x86_64-linux.

2017-04-17  Dennis Wölfing  <denniswoelfing@gmx.de>

	* malloc/Makefile (routines): Add reallocarray.
	* malloc/malloc-private.h: New file.
	(check_mul_overflow): Use __builtin_mul_overflow if available.
	* malloc/malloc.c (check_mul_overflow): Move to malloc-private.h.
	(reallocarray): Move to reallocarray.c.
	* malloc/reallocarray.c: New file.
	* manual/memory.texi: Document reallocarray.
	* stdlib/stdlib.h (reallocarray): Declare only for __USE_GNU.
	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

2017-04-17  Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/Makefile (tests): Add tst-reallocarray.c.
	* malloc/tst-reallocarray.c: New test file.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/malloc.c (check_mul_overflow): New inline function.
	(__libc_reallocarray): New function.
	(__libc_calloc): Use `check_mul_overflow'.
---
 malloc/Makefile                                    |   4 +-
 malloc/Versions                                    |   6 +
 malloc/malloc-private.h                            |  44 ++++++
 malloc/malloc.c                                    |  14 +-
 malloc/malloc.h                                    |   8 ++
 malloc/reallocarray.c                              |  35 +++++
 malloc/tst-reallocarray.c                          | 160 +++++++++++++++++++++
 manual/memory.texi                                 |  24 +++-
 stdlib/stdlib.h                                    |  11 ++
 sysdeps/arm/nacl/libc.abilist                      |   2 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   2 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   2 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   2 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   2 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   2 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   2 +
 38 files changed, 350 insertions(+), 14 deletions(-)
 create mode 100644 malloc/malloc-private.h
 create mode 100644 malloc/reallocarray.c
 create mode 100644 malloc/tst-reallocarray.c

diff --git a/malloc/Makefile b/malloc/Makefile
index e93b83b57d..6534594f7f 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
@@ -47,7 +47,7 @@ endif
 tests += $(tests-static)
 test-srcs = tst-mtrace
 
-routines = malloc morecore mcheck mtrace obstack \
+routines = malloc morecore mcheck mtrace obstack reallocarray \
   scratch_buffer_grow scratch_buffer_grow_preserve \
   scratch_buffer_set_array_size
 
diff --git a/malloc/Versions b/malloc/Versions
index f3c3d8a093..23aafb5ccc 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -61,6 +61,9 @@ libc {
   GLIBC_2.16 {
     aligned_alloc;
   }
+  GLIBC_2.26 {
+    reallocarray;
+  }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
     __libc_malloc_pthread_startup;
@@ -72,5 +75,8 @@ libc {
     __libc_scratch_buffer_grow;
     __libc_scratch_buffer_grow_preserve;
     __libc_scratch_buffer_set_array_size;
+
+    # Internal name for reallocarray
+    __libc_reallocarray;
   }
 }
diff --git a/malloc/malloc-private.h b/malloc/malloc-private.h
new file mode 100644
index 0000000000..56b9fbd708
--- /dev/null
+++ b/malloc/malloc-private.h
@@ -0,0 +1,44 @@
+/* Private declarations for malloc, for use within libc.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MALLOC_PRIVATE_H
+#define _MALLOC_PRIVATE_H
+
+#include <malloc/malloc-internal.h>
+
+static inline bool
+check_mul_overflow (size_t l, size_t r, INTERNAL_SIZE_T *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow (l, r, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = l * r;
+# define HALF_INTERNAL_SIZE_T                                   \
+  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
+  if (__glibc_unlikely ((l | r) >= HALF_INTERNAL_SIZE_T))
+    {
+      if (r != 0 && *result / r != l)
+        return true;
+    }
+  return false;
+# undef HALF_INTERNAL_SIZE_T
+#endif
+}
+
+#endif /* _MALLOC_PRIVATE_H */
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 4c40e2ea19..35cf4ec1fe 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -240,6 +240,7 @@
 #include <libc-pointer-arith.h>
 
 #include <malloc/malloc-internal.h>
+#include <malloc/malloc-private.h>
 
 /*
   Debugging:
@@ -3180,17 +3181,10 @@ __libc_calloc (size_t n, size_t elem_size)
   unsigned long nclears;
   INTERNAL_SIZE_T *d;
 
-  /* size_t is unsigned so the behavior on overflow is defined.  */
-  bytes = n * elem_size;
-#define HALF_INTERNAL_SIZE_T \
-  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
-  if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0))
+  if (check_mul_overflow (n, elem_size, &bytes))
     {
-      if (elem_size != 0 && bytes / elem_size != n)
-        {
-          __set_errno (ENOMEM);
-          return 0;
-        }
+      __set_errno (ENOMEM);
+      return 0;
     }
 
   void *(*hook) (size_t, const void *) =
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 0bd8f97bc3..105fdbe691 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+__THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
new file mode 100644
index 0000000000..4915ca7a7d
--- /dev/null
+++ b/malloc/reallocarray.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <malloc.h>
+#include <malloc/malloc-private.h>
+
+void *
+__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
+{
+  INTERNAL_SIZE_T bytes;
+  if (check_mul_overflow (nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return realloc (optr, bytes);
+}
+
+strong_alias (__libc_reallocarray, __reallocarray)
+weak_alias (__libc_reallocarray, reallocarray)
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..a43419b82b
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+  ++errors;
+  printf ("Error: %s.\n", msg);
+}
+
+static int
+do_test (void)
+
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  if (ptr)
+    {
+      merror ("Overflow for size_t MAX * 2 not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  if (ptr)
+    {
+      merror ("Overflow for 2 * size_t MAX not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  if (ptr)
+    {
+      merror ("Overflow for (size_t MAX/65537 + 1) * 65537 not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  if (ptr)
+    {
+      merror ("Overflow for 65537 * (size_t MAX/65537 + 1)  not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray (NULL, 10, 2);
+  if (!ptr)
+    merror ("realloc(NULL, 10, 2) failed");
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray (ptr, 20, 2);
+  if (!ptr2)
+    merror ("realloc(ptr, 20, 2) failed (enlarge)");
+  else
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Enlarging changed buffer content (10*2)");
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray (ptr, 5, 3);
+  if (!ptr2)
+    merror ("realloc(ptr, 5, 3) failed (decrease)");
+  else
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Reducing changed buffer content (5*3)");
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 2, ~(size_t)0);
+  if (ptr2)
+    merror ("realloc(ptr, 2, size_t MAX) failed to detect overflow");
+  if (errno != ENOMEM)
+    merror ("errno not set correctly");
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Overflow changed buffer content (5*3)");
+
+  /* Free buffer (glibc).  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 0, 0);
+  if (ptr2)
+    merror ("reallocarray (ptr, 0, 0) returned non-NULL");
+
+  free (ptr2);
+
+  return errors != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/manual/memory.texi b/manual/memory.texi
index 38d3c3a4bb..3658fef647 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -756,8 +756,8 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
 @comment malloc.h stdlib.h
@@ -821,6 +821,21 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
+@comment malloc.h stdlib.h
+@comment BSD
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails if the
+multiplication overflows.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+@end deftypefun
+
 Like @code{malloc}, @code{realloc} may return a null pointer if no
 memory space is available to make the block bigger.  When this happens,
 the original block is untouched; it has not been modified or relocated.
@@ -1593,6 +1608,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index c1f389253a..dad94dcc74 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index abd70c8108..b60bf7049a 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1853,3 +1853,5 @@ GLIBC_2.25 gnu_dev_minor F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..a494c3947d 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..2fc1a9bae7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..4465a62ff1 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..96126d9e6a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..aae351bbff 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..81ec65bec0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..9db205b68e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..ee59e950b6 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..feb869757c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..a5b1c42929 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..570a859aac 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..71008ad873 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..1a07d66caf 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..a62a41be62 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..f4f11dc625 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..2977569f2c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..271d32e19b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..372ef67c27 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..705ff851a9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..21fd2b5671 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..313a71e589 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..94a4fb2213 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..6db5811c3f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..ce14ceb15f 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..f69de7aa83 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..a330855308 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
-- 
2.12.2

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-17 14:02 ` [PATCH v2] " Dennis Wölfing
@ 2017-04-17 14:32   ` Florian Weimer
  2017-04-17 14:34     ` Paul Eggert
  2017-04-17 14:40     ` Dennis Wölfing
  2017-04-18 12:34   ` Carlos O'Donell
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 48+ messages in thread
From: Florian Weimer @ 2017-04-17 14:32 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha

* Dennis Wölfing:

> +static inline bool
> +check_mul_overflow (size_t l, size_t r, INTERNAL_SIZE_T *result)
> +{
> +#if __GNUC__ >= 5
> +  return __builtin_mul_overflow (l, r, result);

This is not correct for size_t != INTERNAL_SIZE_T.  Either change the
type of result to size_t * (so that the code fails to compile if the
types differ, something which we have not done for a long time), or
add another check against (INTERNAL_SIZE_T) -1.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-17 14:32   ` Florian Weimer
@ 2017-04-17 14:34     ` Paul Eggert
  2017-04-17 14:40     ` Dennis Wölfing
  1 sibling, 0 replies; 48+ messages in thread
From: Paul Eggert @ 2017-04-17 14:34 UTC (permalink / raw)
  To: Florian Weimer, Dennis Wölfing; +Cc: libc-alpha

On 04/17/2017 07:32 AM, Florian Weimer wrote:
> * Dennis Wölfing:
>
>> +static inline bool
>> +check_mul_overflow (size_t l, size_t r, INTERNAL_SIZE_T *result)
>> +{
>> +#if __GNUC__ >= 5
>> +  return __builtin_mul_overflow (l, r, result);
> This is not correct for size_t != INTERNAL_SIZE_T.

Why not? Could you give an example?

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-17 14:32   ` Florian Weimer
  2017-04-17 14:34     ` Paul Eggert
@ 2017-04-17 14:40     ` Dennis Wölfing
  2017-04-17 14:44       ` Florian Weimer
  1 sibling, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-17 14:40 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 17.04.2017 16:32, Florian Weimer wrote:
> * Dennis Wölfing:
> 
>> +static inline bool
>> +check_mul_overflow (size_t l, size_t r, INTERNAL_SIZE_T *result)
>> +{
>> +#if __GNUC__ >= 5
>> +  return __builtin_mul_overflow (l, r, result);
> 
> This is not correct for size_t != INTERNAL_SIZE_T.  Either change the
> type of result to size_t * (so that the code fails to compile if the
> types differ, something which we have not done for a long time), or
> add another check against (INTERNAL_SIZE_T) -1.

Are you sure that this is not correct? The GCC manual says about the
overflow builtins:

> These built-in functions promote the first two operands into infinite
> precision signed type and perform addition on those promoted operands.
> The result is then cast to the type the third pointer argument points
> to and stored there. If the stored result is equal to the infinite
> precision result, the built-in functions return false, otherwise they
> return true. As the addition is performed in infinite signed
> precision, these built-in functions have fully defined behavior for
> all argument values.

So the result should be correct even if the types are different.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-17 14:40     ` Dennis Wölfing
@ 2017-04-17 14:44       ` Florian Weimer
  0 siblings, 0 replies; 48+ messages in thread
From: Florian Weimer @ 2017-04-17 14:44 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha

* Dennis Wölfing:

> On 17.04.2017 16:32, Florian Weimer wrote:
>> * Dennis Wölfing:
>> 
>>> +static inline bool
>>> +check_mul_overflow (size_t l, size_t r, INTERNAL_SIZE_T *result)
>>> +{
>>> +#if __GNUC__ >= 5
>>> +  return __builtin_mul_overflow (l, r, result);
>> 
>> This is not correct for size_t != INTERNAL_SIZE_T.  Either change the
>> type of result to size_t * (so that the code fails to compile if the
>> types differ, something which we have not done for a long time), or
>> add another check against (INTERNAL_SIZE_T) -1.
>
> Are you sure that this is not correct? The GCC manual says about the
> overflow builtins:

Sorry, you are right.  I actually tested this, but misread the
generated assembly.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-17 14:02 ` [PATCH v2] " Dennis Wölfing
  2017-04-17 14:32   ` Florian Weimer
@ 2017-04-18 12:34   ` Carlos O'Donell
  2017-04-18 14:29     ` Dennis Wölfing
  2017-04-19 15:02   ` Joseph Myers
  2017-04-21 12:16   ` [PATCH v3] " Dennis Wölfing
  3 siblings, 1 reply; 48+ messages in thread
From: Carlos O'Donell @ 2017-04-18 12:34 UTC (permalink / raw)
  To: Dennis Wölfing, libc-alpha

On 04/17/2017 10:01 AM, Dennis Wölfing wrote:
> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
> 
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
> 
> Tested on x86_64-linux.

Rüdiger Sonderfeld has a future's copyright assignment for glibc, which
means we can accept work from Rüdiger.

However, we have no such assignment that I can see for yourself. It isn't
clear exactly how much you changed from Rüdiger's originally submitted
works. Say you only changed ~15 legally significant lines, then we might
be able to accept the new patch, but it would certainly need both author
names in the ChangeLog.

Would you consider signing a future's copyright assignment for glibc so
we can accept your present and future work for the project? Such an assignment
would allow us as maintainers to accept your current and all future work
submitted to the project.

https://sourceware.org/glibc/wiki/Contribution%20checklist

https://sourceware.org/glibc/wiki/Contribution%20checklist#FSF_copyright_Assignment

http://git.savannah.gnu.org/cgit/gnulib.git/plain/doc/Copyright/request-assign.future

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-18 12:34   ` Carlos O'Donell
@ 2017-04-18 14:29     ` Dennis Wölfing
  2017-04-18 15:50       ` Carlos O'Donell
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-18 14:29 UTC (permalink / raw)
  To: Carlos O'Donell, libc-alpha

On 18.04.2017 14:34, Carlos O'Donell wrote:
> However, we have no such assignment that I can see for yourself.

I have already assigned copyright for glibc to the FSF and got it back
signed by the FSF.

I will send you a copy of the signed copyright papers in a separate mail.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-18 14:29     ` Dennis Wölfing
@ 2017-04-18 15:50       ` Carlos O'Donell
  2017-04-18 15:57         ` Dennis Wölfing
  0 siblings, 1 reply; 48+ messages in thread
From: Carlos O'Donell @ 2017-04-18 15:50 UTC (permalink / raw)
  To: Dennis Wölfing, libc-alpha

On 04/18/2017 10:28 AM, Dennis Wölfing wrote:
> On 18.04.2017 14:34, Carlos O'Donell wrote:
>> However, we have no such assignment that I can see for yourself.
> 
> I have already assigned copyright for glibc to the FSF and got it back
> signed by the FSF.
> 
> I will send you a copy of the signed copyright papers in a separate mail.
 
Thank you for proactively taking that step.

Your assignment is not yet on file with the FSF for me to review, this is
likely because your assignment was just recently completed last week.

However, given your assignment papers that makes it easy for the technical
review to continue.

My only remaining issue is that the works you present are based on Sonderfeld's
work, and should include his name in the ChangeLog to give credit for the basis
of the work.

e.g.

2017-04-17  Dennis Wölfing  <denniswoelfing@gmx.de>
	    Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* ...

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-18 15:50       ` Carlos O'Donell
@ 2017-04-18 15:57         ` Dennis Wölfing
  2017-04-19 15:16           ` Joseph Myers
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-18 15:57 UTC (permalink / raw)
  To: Carlos O'Donell, libc-alpha

On 18.04.2017 17:50, Carlos O'Donell wrote:> My only remaining issue is
that the works you present are based on Sonderfeld's
> work, and should include his name in the ChangeLog to give credit for the basis
> of the work.
> 
> e.g.
> 
> 2017-04-17  Dennis Wölfing  <denniswoelfing@gmx.de>
> 	    Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
> 
> 	* ...
> 

The patch I have submitted already contains two separate ChangeLog entries:

2017-04-17  Dennis Wölfing  <denniswoelfing@gmx.de>

	* ...

2017-04-17  Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/Makefile (tests): Add tst-reallocarray.c.
	* malloc/tst-reallocarray.c: New test file.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/malloc.c (check_mul_overflow): New inline function.
	(__libc_reallocarray): New function.
	(__libc_calloc): Use `check_mul_overflow'.

Should I merge these entries?

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-17 14:02 ` [PATCH v2] " Dennis Wölfing
  2017-04-17 14:32   ` Florian Weimer
  2017-04-18 12:34   ` Carlos O'Donell
@ 2017-04-19 15:02   ` Joseph Myers
  2017-04-21 12:16   ` [PATCH v3] " Dennis Wölfing
  3 siblings, 0 replies; 48+ messages in thread
From: Joseph Myers @ 2017-04-19 15:02 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 1422 bytes --]

On Mon, 17 Apr 2017, Dennis Wölfing wrote:

> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
> 
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

A patch adding a new function should also include NEWS file changes to 
mention that new feature.

> diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
> new file mode 100644
> index 0000000000..4915ca7a7d
> --- /dev/null
> +++ b/malloc/reallocarray.c
> @@ -0,0 +1,35 @@
> +/* Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.

New files should have a descriptive comment on their first line, before 
the copyright notice.

> diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
> new file mode 100644
> index 0000000000..a43419b82b
> --- /dev/null
> +++ b/malloc/tst-reallocarray.c
> @@ -0,0 +1,160 @@
> +/* Copyright (C) 2014-2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.

Likewise.

> +#define TEST_FUNCTION do_test ()
> +#include "../test-skeleton.c"

Please use the new-style support/test-driver.c for new tests.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v2] Add reallocarray function.
  2017-04-18 15:57         ` Dennis Wölfing
@ 2017-04-19 15:16           ` Joseph Myers
  0 siblings, 0 replies; 48+ messages in thread
From: Joseph Myers @ 2017-04-19 15:16 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: Carlos O'Donell, libc-alpha

[-- Attachment #1: Type: text/plain, Size: 1386 bytes --]

On Tue, 18 Apr 2017, Dennis Wölfing wrote:

> On 18.04.2017 17:50, Carlos O'Donell wrote:> My only remaining issue is
> that the works you present are based on Sonderfeld's
> > work, and should include his name in the ChangeLog to give credit for the basis
> > of the work.
> > 
> > e.g.
> > 
> > 2017-04-17  Dennis Wölfing  <denniswoelfing@gmx.de>
> > 	    Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
> > 
> > 	* ...
> > 
> 
> The patch I have submitted already contains two separate ChangeLog entries:
> 
> 2017-04-17  Dennis Wölfing  <denniswoelfing@gmx.de>
> 
> 	* ...
> 
> 2017-04-17  Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
> 
> 	* malloc/Versions: Add reallocarray and __libc_reallocarray.
> 	* malloc/Makefile (tests): Add tst-reallocarray.c.
> 	* malloc/tst-reallocarray.c: New test file.
> 	* malloc/malloc.h (reallocarray): New declaration.
> 	* stdlib/stdlib.h (reallocarray): Likewise.
> 	* malloc/malloc.c (check_mul_overflow): New inline function.
> 	(__libc_reallocarray): New function.
> 	(__libc_calloc): Use `check_mul_overflow'.
> 
> Should I merge these entries?

Yes.  There should be a single entry, with both names, describing the 
actual set of changes proposed for commit.  There should not be a separate 
ChangeLog entry relating to an intermediate set of changes not committed 
in that state.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v3] Add reallocarray function.
  2017-04-17 14:02 ` [PATCH v2] " Dennis Wölfing
                     ` (2 preceding siblings ...)
  2017-04-19 15:02   ` Joseph Myers
@ 2017-04-21 12:16   ` Dennis Wölfing
  2017-04-28  8:57     ` Dennis Wölfing
  2017-05-08  7:34     ` Florian Weimer
  3 siblings, 2 replies; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-21 12:16 UTC (permalink / raw)
  To: libc-alpha

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on x86_64-linux.

2017-04-21  Dennis Wölfing  <denniswoelfing@gmx.de>
            Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* NEWS: Mention addition of reallocarray.
	* malloc/Makefile (routines): Add reallocarray.
	(tests): Add tst-reallocarray.c.
	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/malloc-private.h: New file.
	* malloc/malloc.c (__libc_calloc): Use `check_mul_overflow'.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/reallocarray.c: New file.
	* malloc/tst-reallocarray.c: New test file.
	* manual/memory.texi: Document reallocarray.
	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
---
 NEWS                                               |   2 +
 malloc/Makefile                                    |   4 +-
 malloc/Versions                                    |   4 +
 malloc/malloc-private.h                            |  44 ++++++
 malloc/malloc.c                                    |  14 +-
 malloc/malloc.h                                    |   8 ++
 malloc/reallocarray.c                              |  36 +++++
 malloc/tst-reallocarray.c                          | 159 +++++++++++++++++++++
 manual/memory.texi                                 |  24 +++-
 stdlib/stdlib.h                                    |  11 ++
 sysdeps/arm/nacl/libc.abilist                      |   2 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   2 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   2 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   2 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   2 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   2 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   2 +
 39 files changed, 350 insertions(+), 14 deletions(-)
 create mode 100644 malloc/malloc-private.h
 create mode 100644 malloc/reallocarray.c
 create mode 100644 malloc/tst-reallocarray.c

diff --git a/NEWS b/NEWS
index 811178bca6..eaee4af5f5 100644
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,8 @@ Version 2.26
 * The legacy cfree function has been removed.  Applications should use the
   free function instead.
 
+* The reallocarray function has been added to libc.
+
 Security related changes:
 
 * The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes,
diff --git a/malloc/Makefile b/malloc/Makefile
index e93b83b57d..6534594f7f 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
@@ -47,7 +47,7 @@ endif
 tests += $(tests-static)
 test-srcs = tst-mtrace
 
-routines = malloc morecore mcheck mtrace obstack \
+routines = malloc morecore mcheck mtrace obstack reallocarray \
   scratch_buffer_grow scratch_buffer_grow_preserve \
   scratch_buffer_set_array_size
 
diff --git a/malloc/Versions b/malloc/Versions
index e34ab177be..23aafb5ccc 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -62,6 +62,7 @@ libc {
     aligned_alloc;
   }
   GLIBC_2.26 {
+    reallocarray;
   }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
@@ -74,5 +75,8 @@ libc {
     __libc_scratch_buffer_grow;
     __libc_scratch_buffer_grow_preserve;
     __libc_scratch_buffer_set_array_size;
+
+    # Internal name for reallocarray
+    __libc_reallocarray;
   }
 }
diff --git a/malloc/malloc-private.h b/malloc/malloc-private.h
new file mode 100644
index 0000000000..56b9fbd708
--- /dev/null
+++ b/malloc/malloc-private.h
@@ -0,0 +1,44 @@
+/* Private declarations for malloc, for use within libc.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MALLOC_PRIVATE_H
+#define _MALLOC_PRIVATE_H
+
+#include <malloc/malloc-internal.h>
+
+static inline bool
+check_mul_overflow (size_t l, size_t r, INTERNAL_SIZE_T *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow (l, r, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = l * r;
+# define HALF_INTERNAL_SIZE_T                                   \
+  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
+  if (__glibc_unlikely ((l | r) >= HALF_INTERNAL_SIZE_T))
+    {
+      if (r != 0 && *result / r != l)
+        return true;
+    }
+  return false;
+# undef HALF_INTERNAL_SIZE_T
+#endif
+}
+
+#endif /* _MALLOC_PRIVATE_H */
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 068ffc1684..a21910c4eb 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -239,6 +239,7 @@
 #include <libc-pointer-arith.h>
 
 #include <malloc/malloc-internal.h>
+#include <malloc/malloc-private.h>
 
 /*
   Debugging:
@@ -3179,17 +3180,10 @@ __libc_calloc (size_t n, size_t elem_size)
   unsigned long nclears;
   INTERNAL_SIZE_T *d;
 
-  /* size_t is unsigned so the behavior on overflow is defined.  */
-  bytes = n * elem_size;
-#define HALF_INTERNAL_SIZE_T \
-  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
-  if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0))
+  if (check_mul_overflow (n, elem_size, &bytes))
     {
-      if (elem_size != 0 && bytes / elem_size != n)
-        {
-          __set_errno (ENOMEM);
-          return 0;
-        }
+      __set_errno (ENOMEM);
+      return 0;
     }
 
   void *(*hook) (size_t, const void *) =
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 274c0958e4..339ab64c7d 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+__THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
new file mode 100644
index 0000000000..0755f2ab90
--- /dev/null
+++ b/malloc/reallocarray.c
@@ -0,0 +1,36 @@
+/* Change the size of an allocated block.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <malloc.h>
+#include <malloc/malloc-private.h>
+
+void *
+__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
+{
+  INTERNAL_SIZE_T bytes;
+  if (check_mul_overflow (nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return realloc (optr, bytes);
+}
+
+strong_alias (__libc_reallocarray, __reallocarray)
+weak_alias (__libc_reallocarray, reallocarray)
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..2d82c9d3da
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,159 @@
+/* Test for reallocarray.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+  ++errors;
+  printf ("Error: %s.\n", msg);
+}
+
+static int
+do_test (void)
+
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  if (ptr)
+    {
+      merror ("Overflow for size_t MAX * 2 not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  if (ptr)
+    {
+      merror ("Overflow for 2 * size_t MAX not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  if (ptr)
+    {
+      merror ("Overflow for (size_t MAX/65537 + 1) * 65537 not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  if (ptr)
+    {
+      merror ("Overflow for 65537 * (size_t MAX/65537 + 1)  not detected");
+      free (ptr);
+    }
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly");
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray (NULL, 10, 2);
+  if (!ptr)
+    merror ("realloc(NULL, 10, 2) failed");
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray (ptr, 20, 2);
+  if (!ptr2)
+    merror ("realloc(ptr, 20, 2) failed (enlarge)");
+  else
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Enlarging changed buffer content (10*2)");
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray (ptr, 5, 3);
+  if (!ptr2)
+    merror ("realloc(ptr, 5, 3) failed (decrease)");
+  else
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Reducing changed buffer content (5*3)");
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 2, ~(size_t)0);
+  if (ptr2)
+    merror ("realloc(ptr, 2, size_t MAX) failed to detect overflow");
+  if (errno != ENOMEM)
+    merror ("errno not set correctly");
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  if (!ok)
+    merror ("Overflow changed buffer content (5*3)");
+
+  /* Free buffer (glibc).  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 0, 0);
+  if (ptr2)
+    merror ("reallocarray (ptr, 0, 0) returned non-NULL");
+
+  free (ptr2);
+
+  return errors != 0;
+}
+
+#include <support/test-driver.c>
diff --git a/manual/memory.texi b/manual/memory.texi
index a256ca07b2..9758365eb7 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -751,8 +751,8 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
 @comment malloc.h stdlib.h
@@ -816,6 +816,21 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
+@comment malloc.h stdlib.h
+@comment BSD
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails if the
+multiplication overflows.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+@end deftypefun
+
 Like @code{malloc}, @code{realloc} may return a null pointer if no
 memory space is available to make the block bigger.  When this happens,
 the original block is untouched; it has not been modified or relocated.
@@ -1588,6 +1603,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 99125f2d23..428ca2ef68 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index abd70c8108..b60bf7049a 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1853,3 +1853,5 @@ GLIBC_2.25 gnu_dev_minor F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..a494c3947d 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..2fc1a9bae7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..4465a62ff1 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..96126d9e6a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..aae351bbff 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..81ec65bec0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..9db205b68e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..ee59e950b6 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..feb869757c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..a5b1c42929 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..570a859aac 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..71008ad873 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..1a07d66caf 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..a62a41be62 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..f4f11dc625 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..2977569f2c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..271d32e19b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..372ef67c27 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..705ff851a9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..21fd2b5671 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..313a71e589 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..94a4fb2213 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..6db5811c3f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..ce14ceb15f 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..f69de7aa83 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..a330855308 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
-- 
2.12.2

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v3] Add reallocarray function.
  2017-04-21 12:16   ` [PATCH v3] " Dennis Wölfing
@ 2017-04-28  8:57     ` Dennis Wölfing
  2017-05-08  7:07       ` Dennis Wölfing
  2017-05-08  7:34     ` Florian Weimer
  1 sibling, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-04-28  8:57 UTC (permalink / raw)
  To: libc-alpha

On 21.04.2017 14:16, Dennis Wölfing wrote:
> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
> 
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
> 
> Tested on x86_64-linux.
> 
> 2017-04-21  Dennis Wölfing  <denniswoelfing@gmx.de>
>             Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
> 
> 	* NEWS: Mention addition of reallocarray.
> 	* malloc/Makefile (routines): Add reallocarray.
> 	(tests): Add tst-reallocarray.c.
> 	* malloc/Versions: Add reallocarray and __libc_reallocarray.
> 	* malloc/malloc-private.h: New file.
> 	* malloc/malloc.c (__libc_calloc): Use `check_mul_overflow'.
> 	* malloc/malloc.h (reallocarray): New declaration.
> 	* stdlib/stdlib.h (reallocarray): Likewise.
> 	* malloc/reallocarray.c: New file.
> 	* malloc/tst-reallocarray.c: New test file.
> 	* manual/memory.texi: Document reallocarray.
> 	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

Ping

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v3] Add reallocarray function.
  2017-04-28  8:57     ` Dennis Wölfing
@ 2017-05-08  7:07       ` Dennis Wölfing
  0 siblings, 0 replies; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-08  7:07 UTC (permalink / raw)
  To: libc-alpha

On 28.04.2017 10:57, Dennis Wölfing wrote:
> On 21.04.2017 14:16, Dennis Wölfing wrote:
>> The reallocarray function is an extension from OpenBSD.  It is an
>> integer-overflow-safe replacement for realloc(p, X*Y) and
>> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
>> certain security issues in code.
>>
>> This is an updated version of a patch originally submitted by Rüdiger
>> Sonderfeld in May 2014.
>> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
>>
>> Tested on x86_64-linux.
>>
>> 2017-04-21  Dennis Wölfing  <denniswoelfing@gmx.de>
>>             Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
>>
>> 	* NEWS: Mention addition of reallocarray.
>> 	* malloc/Makefile (routines): Add reallocarray.
>> 	(tests): Add tst-reallocarray.c.
>> 	* malloc/Versions: Add reallocarray and __libc_reallocarray.
>> 	* malloc/malloc-private.h: New file.
>> 	* malloc/malloc.c (__libc_calloc): Use `check_mul_overflow'.
>> 	* malloc/malloc.h (reallocarray): New declaration.
>> 	* stdlib/stdlib.h (reallocarray): Likewise.
>> 	* malloc/reallocarray.c: New file.
>> 	* malloc/tst-reallocarray.c: New test file.
>> 	* manual/memory.texi: Document reallocarray.
>> 	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
>> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
>> 	Likewise.
>> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
>> 	Likewise.
>> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
>> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
>
> Ping

Ping 2. This patch
<https://sourceware.org/ml/libc-alpha/2017-04/msg00454.html>
is still pending.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v3] Add reallocarray function.
  2017-04-21 12:16   ` [PATCH v3] " Dennis Wölfing
  2017-04-28  8:57     ` Dennis Wölfing
@ 2017-05-08  7:34     ` Florian Weimer
  2017-05-10 13:03       ` [PATCH v4] " Dennis Wölfing
  1 sibling, 1 reply; 48+ messages in thread
From: Florian Weimer @ 2017-05-08  7:34 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha

On 04/21/2017 02:16 PM, Dennis Wölfing wrote:
> +static void
> +merror (const char *msg)
> +{
> +  ++errors;
> +  printf ("Error: %s.\n", msg);
> +}

I don't think this provides additional useful information compared to 
TEST_VERIFY, so you could simply use that.  It's also not necessary to 
free pointers on test failure paths (for allocations which succeeded, 
but should not have), so you can simplify the test a bit further.

Further comments:

In check_mul_overflow, you can use a local variable instead of the 
preprocessor macro HALF_INTERNAL_SIZE_T.

An interposed malloc will not use INTERNAL_SIZE_T and will not interpose 
reallocarray, so reallocarray will fail allocations when it does not 
have to.  I think you need too check_mul_overflow variants, one for use 
in calloc (with INTERNAL_SIZE_T), and one for use in reallocarray.  It's 
probably best to leave calloc alone in this patch and only add a 
size_t-based check_mul_overflow in this patch.

You should add

libc_hidden_proto (__libc_reallocarray)

to include/stdlib.h, matched by

libc_hidden_def (__libc_reallocarray)

in malloc/reallocarray.c.  This way, libc-internal calls to reallocarray 
will not go through the PLT.

I'm not sure if the alias machinery in malloc/reallocarray.c is correct. 
  I think you only need a weak_alias for reallocarray.  (It has to be 
weak to support static linking of glibc-internal calls to 
__libc_reallocarray, without conflicting with a user-supplied 
reallocarray function.)

Otherwise, the patch looks good.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v4] Add reallocarray function.
  2017-05-08  7:34     ` Florian Weimer
@ 2017-05-10 13:03       ` Dennis Wölfing
  2017-05-10 21:29         ` DJ Delorie
  2017-05-15 12:22         ` [PATCH v5] " Dennis Wölfing
  0 siblings, 2 replies; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-10 13:03 UTC (permalink / raw)
  To: libc-alpha; +Cc: fweimer

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on x86_64-linux.

2017-05-10  Dennis Wölfing  <denniswoelfing@gmx.de>
            Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* NEWS: Mention addition of reallocarray.
	* include/stdlib.h (__libc_reallocarray): New declaration.
	* malloc/Makefile (routines): Add reallocarray.
	(tests): Add tst-reallocarray.c.
	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/malloc-private.h: New file.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/reallocarray.c: New file.
	* malloc/tst-reallocarray.c: New test file.
	* manual/memory.texi: Document reallocarray.
	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
---
 NEWS                                               |   2 +
 include/stdlib.h                                   |   4 +
 malloc/Makefile                                    |   4 +-
 malloc/Versions                                    |   4 +
 malloc/malloc-private.h                            |  42 +++++++
 malloc/malloc.h                                    |   8 ++
 malloc/reallocarray.c                              |  36 ++++++
 malloc/tst-reallocarray.c                          | 121 +++++++++++++++++++++
 manual/memory.texi                                 |  24 +++-
 stdlib/stdlib.h                                    |  11 ++
 sysdeps/arm/nacl/libc.abilist                      |   2 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   2 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   2 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   2 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   2 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   2 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   2 +
 39 files changed, 310 insertions(+), 4 deletions(-)
 create mode 100644 malloc/malloc-private.h
 create mode 100644 malloc/reallocarray.c
 create mode 100644 malloc/tst-reallocarray.c

diff --git a/NEWS b/NEWS
index 09c302b642..236bbc591f 100644
--- a/NEWS
+++ b/NEWS
@@ -63,6 +63,8 @@ Version 2.26
 
 * The obsolete <sys/ultrasound.h> header file has been removed.
 
+* The reallocarray function has been added to libc.
+
 Security related changes:
 
 * The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes,
diff --git a/include/stdlib.h b/include/stdlib.h
index 929cead59a..7823386b39 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -112,6 +112,10 @@ extern int __posix_memalign (void **memptr, size_t alignment, size_t size);
 extern void *__libc_memalign (size_t alignment, size_t size)
      __attribute_malloc__;
 
+extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __attribute_warn_unused_result__;
+libc_hidden_proto (__libc_reallocarray)
+
 extern int __libc_system (const char *line);
 
 
diff --git a/malloc/Makefile b/malloc/Makefile
index e380e9629b..d6921784f8 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
@@ -47,7 +47,7 @@ endif
 tests += $(tests-static)
 test-srcs = tst-mtrace
 
-routines = malloc morecore mcheck mtrace obstack \
+routines = malloc morecore mcheck mtrace obstack reallocarray \
   scratch_buffer_grow scratch_buffer_grow_preserve \
   scratch_buffer_set_array_size
 
diff --git a/malloc/Versions b/malloc/Versions
index e34ab177be..23aafb5ccc 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -62,6 +62,7 @@ libc {
     aligned_alloc;
   }
   GLIBC_2.26 {
+    reallocarray;
   }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
@@ -74,5 +75,8 @@ libc {
     __libc_scratch_buffer_grow;
     __libc_scratch_buffer_grow_preserve;
     __libc_scratch_buffer_set_array_size;
+
+    # Internal name for reallocarray
+    __libc_reallocarray;
   }
 }
diff --git a/malloc/malloc-private.h b/malloc/malloc-private.h
new file mode 100644
index 0000000000..c900b69b19
--- /dev/null
+++ b/malloc/malloc-private.h
@@ -0,0 +1,42 @@
+/* Private declarations for malloc, for use within libc.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MALLOC_PRIVATE_H
+#define _MALLOC_PRIVATE_H
+
+#include <malloc/malloc-internal.h>
+
+static inline bool
+check_mul_overflow_size_t (size_t l, size_t r, size_t *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow (l, r, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = l * r;
+  size_t half_size_t = ((size_t) 1) << (8 * sizeof (size_t) / 2);
+  if (__glibc_unlikely ((l | r) >= half_size_t))
+    {
+      if (r != 0 && *result / r != l)
+        return true;
+    }
+  return false;
+#endif
+}
+
+#endif /* _MALLOC_PRIVATE_H */
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 274c0958e4..339ab64c7d 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+__THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
new file mode 100644
index 0000000000..ef4de931f0
--- /dev/null
+++ b/malloc/reallocarray.c
@@ -0,0 +1,36 @@
+/* Change the size of an allocated block.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <malloc.h>
+#include <malloc/malloc-private.h>
+
+void *
+__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
+{
+  size_t bytes;
+  if (check_mul_overflow_size_t (nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return realloc (optr, bytes);
+}
+libc_hidden_def (__libc_reallocarray)
+
+weak_alias (__libc_reallocarray, reallocarray)
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..6db9f530e1
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,121 @@
+/* Test for reallocarray.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray (NULL, 10, 2);
+  TEST_VERIFY_EXIT (ptr);
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray (ptr, 20, 2);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray (ptr, 5, 3);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 2, ~(size_t)0);
+  TEST_VERIFY (!ptr2);
+  TEST_VERIFY (errno == ENOMEM);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Free buffer (glibc).  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 0, 0);
+  TEST_VERIFY (!ptr2);
+
+  free (ptr2);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/manual/memory.texi b/manual/memory.texi
index a256ca07b2..9758365eb7 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -751,8 +751,8 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
 @comment malloc.h stdlib.h
@@ -816,6 +816,21 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
+@comment malloc.h stdlib.h
+@comment BSD
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails if the
+multiplication overflows.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+@end deftypefun
+
 Like @code{malloc}, @code{realloc} may return a null pointer if no
 memory space is available to make the block bigger.  When this happens,
 the original block is untouched; it has not been modified or relocated.
@@ -1588,6 +1603,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 99125f2d23..428ca2ef68 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index abd70c8108..b60bf7049a 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1853,3 +1853,5 @@ GLIBC_2.25 gnu_dev_minor F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..a494c3947d 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..2fc1a9bae7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..4465a62ff1 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..96126d9e6a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..aae351bbff 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..81ec65bec0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..9db205b68e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..ee59e950b6 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..feb869757c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..a5b1c42929 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..570a859aac 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..71008ad873 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..1a07d66caf 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..a62a41be62 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..f4f11dc625 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..2977569f2c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..271d32e19b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..372ef67c27 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..705ff851a9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..21fd2b5671 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..313a71e589 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..94a4fb2213 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..6db5811c3f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..ce14ceb15f 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..f69de7aa83 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..a330855308 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
-- 
2.12.2

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v4] Add reallocarray function.
  2017-05-10 13:03       ` [PATCH v4] " Dennis Wölfing
@ 2017-05-10 21:29         ` DJ Delorie
  2017-05-11 17:00           ` Dennis Wölfing
  2017-05-15 12:22         ` [PATCH v5] " Dennis Wölfing
  1 sibling, 1 reply; 48+ messages in thread
From: DJ Delorie @ 2017-05-10 21:29 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha, fweimer


Dennis Wlfing <denniswoelfing@gmx.de> writes:
> The reallocarray function is an extension from OpenBSD.

And seems to be being adopted by many other OSs, too.

> Tested on x86_64-linux.

Could you test on a 32-bit system also?

This declaration:

> diff --git a/include/stdlib.h b/include/stdlib.h
> +extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
> +     __attribute_warn_unused_result__;

Doesn't match this one:

> diff --git a/malloc/malloc.h b/malloc/malloc.h
> +extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
> +__THROW __attribute_warn_unused_result__;

or this one:

> diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
>  extern void *realloc (void *__ptr, size_t __size)
>       __THROW __attribute_warn_unused_result__;

which don't match the definition:

> diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
> +void *
> +__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)

> diff --git a/malloc/malloc-private.h b/malloc/malloc-private.h

I'm confused; we have a malloc-internal.h which doesn't look like it
needs to be included for malloc.h to work; why can't we fix that and use
it, instead of adding a second "internal" header?

(traditionally, we put private things in malloc.c, which includes other
.c files, which is IMHO wrong, but that's a problem for another day ;)

> +#include <malloc/malloc-internal.h>

There doesn't seem to be anything in malloc-internal.h that this header
needs...

> +static inline bool
> +check_mul_overflow_size_t (size_t l, size_t r, size_t *result)

A short comment here that documents the function (returns true/false
when, sets results when) is appropriate.

> +void *
> +__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
> +{
> +  size_t bytes;
> +  if (check_mul_overflow_size_t (nmemb, elem_size, &bytes))

Do we want a __glibc_unlikely() here?

> +  /* Test realloc-like behavior.  */
> +  /* Allocate memory like malloc.  */
> +  ptr = reallocarray (NULL, 10, 2);
> +  TEST_VERIFY_EXIT (ptr);

We should also call __malloc_usable_size() to make sure it's at least
what we expect.

> +  /* Enlarge buffer.   */
> +  ptr2 = reallocarray (ptr, 20, 2);
> +  TEST_VERIFY (ptr2);
> +  if (ptr2)
> +    ptr = ptr2;

Likewise, etc.

> +  /* Overflow should leave buffer untouched.  */

This requirement isn't documented anywhere...

> +  /* Free buffer (glibc).  */

That is not what the BSD version does... realloc of size zero returns a
pointer, and the Austin Group has decided realloc(ptr,0) is not free().
While this might be what we do, do we want to enshrine that in a test
case?

Sine the original definition of this function comes from BSD and we have
no historical reason to violate C99 or the Austin Group, we should have
reallocarray (ptr,0,0) act like those instead of our own historic
realloc().

> +  errno = 0;
> +  ptr2 = reallocarray (ptr, 0, 0);
> +  TEST_VERIFY (!ptr2);
> +
> +  free (ptr2);

Intentional double-free here?  (if so, add a comment... if not, add a
comment ;)

> +@comment malloc.h stdlib.h
> +@comment BSD
> +@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
> +
> +The @code{reallocarray} function changes the size of the block whose address
> +is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
> +each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
> +@var{nmemb} * @var{size})}, except that @code{reallocarray} fails if the
> +multiplication overflows.
> +
> +@code{reallocarray} should be used instead of @code{realloc} when the new size
> +of the allocated block is the result of a multiplication that might overflow.
> +@end deftypefun

This chunk appears right before a paragraph about realloc:

>  Like @code{malloc}, @code{realloc} may return a null pointer if no
>  memory space is available to make the block bigger.  When this happens,
>  the original block is untouched; it has not been modified or relocated.

Is there a better way to add that chunk of text?  Or mention
reallocarray in the surrounding text so it integrates better?

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v4] Add reallocarray function.
  2017-05-10 21:29         ` DJ Delorie
@ 2017-05-11 17:00           ` Dennis Wölfing
  2017-05-11 17:28             ` DJ Delorie
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-11 17:00 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha, fweimer

On 10.05.2017 23:29, DJ Delorie wrote:
> 
> Dennis Wlfing <denniswoelfing@gmx.de> writes:
>> The reallocarray function is an extension from OpenBSD.
> 
> And seems to be being adopted by many other OSs, too.
> 
>> Tested on x86_64-linux.
> 
> Could you test on a 32-bit system also?

I will test it on a i686 system.

> This declaration:
> 
>> diff --git a/include/stdlib.h b/include/stdlib.h
>> +extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
>> +     __attribute_warn_unused_result__;
> 
> Doesn't match this one:
> 
>> diff --git a/malloc/malloc.h b/malloc/malloc.h
>> +extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
>> +__THROW __attribute_warn_unused_result__;
> 
> or this one:
> 
>> diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
>>  extern void *realloc (void *__ptr, size_t __size)
>>       __THROW __attribute_warn_unused_result__;
> 
> which don't match the definition:
> 
>> diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
>> +void *
>> +__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)

The header include/stdlib.h (not to be confused with stdlib/stdlib.h) is
an internal glibc header. It declares the function prefixed with __libc_
so that other glibc functions can call it without causing namespace
problems. In the public headers only reallocarray is declared which is a
weak alias for __libc_reallocarray.

>> diff --git a/malloc/malloc-private.h b/malloc/malloc-private.h
> 
> I'm confused; we have a malloc-internal.h which doesn't look like it
> needs to be included for malloc.h to work; why can't we fix that and use
> it, instead of adding a second "internal" header?
> 
> (traditionally, we put private things in malloc.c, which includes other
> .c files, which is IMHO wrong, but that's a problem for another day ;)

The check_mul_overflow_size_t function was put in the new
malloc-private.h header because malloc-internal.h is also used in other
parts of glibc.
The reason why it is in a header and not just in reallocarray.c is that
this function can also be useful in other functions. Florian Weimer
currently has two pending patches that also use an equivalent function
and then these patches could just include that header:
https://sourceware.org/ml/libc-alpha/2017-04/msg00498.html
https://sourceware.org/ml/libc-alpha/2017-04/msg00501.html

>> +#include <malloc/malloc-internal.h>
> 
> There doesn't seem to be anything in malloc-internal.h that this header
> needs...

Right, previous versions of this patch used INTERNAL_SIZE_T from
malloc-internal.h but this is not used anymore. I will remove this include.

>> +static inline bool
>> +check_mul_overflow_size_t (size_t l, size_t r, size_t *result)
> 
> A short comment here that documents the function (returns true/false
> when, sets results when) is appropriate.

I will add one.

>> +void *
>> +__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
>> +{
>> +  size_t bytes;
>> +  if (check_mul_overflow_size_t (nmemb, elem_size, &bytes))
> 
> Do we want a __glibc_unlikely() here?

Since check_mul_overflow_size_t is an inline function, I guess the
compiler should be smart enough to get the branch prediction right.
But I could probably add another __glibc_unlikely() around the
r != 0 && *result / r != l condition in check_mul_overflow_size_t.

>> +  /* Test realloc-like behavior.  */
>> +  /* Allocate memory like malloc.  */
>> +  ptr = reallocarray (NULL, 10, 2);
>> +  TEST_VERIFY_EXIT (ptr);
> 
> We should also call __malloc_usable_size() to make sure it's at least
> what we expect.

I will add this.

>> +  /* Enlarge buffer.   */
>> +  ptr2 = reallocarray (ptr, 20, 2);
>> +  TEST_VERIFY (ptr2);
>> +  if (ptr2)
>> +    ptr = ptr2;
> 
> Likewise, etc.
> 
>> +  /* Overflow should leave buffer untouched.  */
> 
> This requirement isn't documented anywhere...

The reallocarray documentation says that reallocarray is equivalent to
realloc(ptr, nmemb*size) and the realloc documentation says it does not
modify the memory block on failure.
But this could probably be documented more explicitly.

>> +  /* Free buffer (glibc).  */
> 
> That is not what the BSD version does... realloc of size zero returns a
> pointer, and the Austin Group has decided realloc(ptr,0) is not free().
> While this might be what we do, do we want to enshrine that in a test
> case?
> 
> Sine the original definition of this function comes from BSD and we have
> no historical reason to violate C99 or the Austin Group, we should have
> reallocarray (ptr,0,0) act like those instead of our own historic
> realloc().

I think reallocarray should just remain a wrapper for realloc that
checks for overflow. So reallocarray(ptr,0,0) should behave like
realloc(ptr,0*0).
I also don't like the realloc(ptr,0) behavior in glibc but it seems like
the C committee wants to allow the glibc behavior by making behavior
implementation defined when size is 0.
http://open-std.org/JTC1/SC22/WG14/www/docs/dr_400.htm
When realloc(ptr,0) is allowed to free ptr reallocarray(ptr,0,0) should
also be.

However I will remove this test because freeing with reallocarray is not
a portable.

>> +  errno = 0;
>> +  ptr2 = reallocarray (ptr, 0, 0);
>> +  TEST_VERIFY (!ptr2);
>> +
>> +  free (ptr2);
> 
> Intentional double-free here?  (if so, add a comment... if not, add a
> comment ;)

Since I will remove the test above this will no longer be a double free.

>> +@comment malloc.h stdlib.h
>> +@comment BSD
>> +@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
>> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
>> +
>> +The @code{reallocarray} function changes the size of the block whose address
>> +is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
>> +each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
>> +@var{nmemb} * @var{size})}, except that @code{reallocarray} fails if the
>> +multiplication overflows.
>> +
>> +@code{reallocarray} should be used instead of @code{realloc} when the new size
>> +of the allocated block is the result of a multiplication that might overflow.
>> +@end deftypefun
> 
> This chunk appears right before a paragraph about realloc:
> 
>>  Like @code{malloc}, @code{realloc} may return a null pointer if no
>>  memory space is available to make the block bigger.  When this happens,
>>  the original block is untouched; it has not been modified or relocated.
> 
> Is there a better way to add that chunk of text?  Or mention
> reallocarray in the surrounding text so it integrates better?

I guess I could change most occurrences of @code{realloc} in that
section by @code{realloc} and @code{reallocarray}.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v4] Add reallocarray function.
  2017-05-11 17:00           ` Dennis Wölfing
@ 2017-05-11 17:28             ` DJ Delorie
  2017-05-11 18:36               ` Dennis Wölfing
  0 siblings, 1 reply; 48+ messages in thread
From: DJ Delorie @ 2017-05-11 17:28 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha, fweimer


Dennis Wlfing <denniswoelfing@gmx.de> writes:
>>> diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
>>> +void *
>>> +__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
>
> The header include/stdlib.h (not to be confused with stdlib/stdlib.h) is
> an internal glibc header. It declares the function prefixed with __libc_
> so that other glibc functions can call it without causing namespace
> problems. In the public headers only reallocarray is declared which is a
> weak alias for __libc_reallocarray.

I was mostly concerned with the __THROW differences.  I've seen those
cause problems in the past.

> The check_mul_overflow_size_t function was put in the new
> malloc-private.h header because malloc-internal.h is also used in other
> parts of glibc.

I have no problems with other parts of glibc seeing it, as long as it
has a suitable name.  I'm just trying to avoid having too many headers
without a good reason for them.

>>> +  /* Overflow should leave buffer untouched.  */
>> 
>> This requirement isn't documented anywhere...
>
> The reallocarray documentation says that reallocarray is equivalent to
> realloc(ptr, nmemb*size) and the realloc documentation says it does not
> modify the memory block on failure.

True, but overflow is a new condition that realloc doesn't have, that's
all, and since overflow checking is the *reason* for reallocarray, it
makes sense to clarify how it works.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v4] Add reallocarray function.
  2017-05-11 17:28             ` DJ Delorie
@ 2017-05-11 18:36               ` Dennis Wölfing
  2017-05-11 18:41                 ` DJ Delorie
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-11 18:36 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha, fweimer

On 11.05.2017 19:28, DJ Delorie wrote:> Dennis Wlfing
<denniswoelfing@gmx.de> writes:
>>>> diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
>>>> +void *
>>>> +__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
>>
>> The header include/stdlib.h (not to be confused with stdlib/stdlib.h) is
>> an internal glibc header. It declares the function prefixed with __libc_
>> so that other glibc functions can call it without causing namespace
>> problems. In the public headers only reallocarray is declared which is a
>> weak alias for __libc_reallocarray.
> 
> I was mostly concerned with the __THROW differences.  I've seen those
> cause problems in the past.

Okay, I will add the __THROW.

>> The check_mul_overflow_size_t function was put in the new
>> malloc-private.h header because malloc-internal.h is also used in other
>> parts of glibc.
> 
> I have no problems with other parts of glibc seeing it, as long as it
> has a suitable name.  I'm just trying to avoid having too many headers
> without a good reason for them.

So putting check_mul_overflow_size_t() into malloc-internal.h is
preferred over malloc-private.h?

>>>> +  /* Overflow should leave buffer untouched.  */
>>>
>>> This requirement isn't documented anywhere...
>>
>> The reallocarray documentation says that reallocarray is equivalent to
>> realloc(ptr, nmemb*size) and the realloc documentation says it does not
>> modify the memory block on failure.
> 
> True, but overflow is a new condition that realloc doesn't have, that's
> all, and since overflow checking is the *reason* for reallocarray, it
> makes sense to clarify how it works.
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v4] Add reallocarray function.
  2017-05-11 18:36               ` Dennis Wölfing
@ 2017-05-11 18:41                 ` DJ Delorie
  0 siblings, 0 replies; 48+ messages in thread
From: DJ Delorie @ 2017-05-11 18:41 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha, fweimer


Dennis Wlfing <denniswoelfing@gmx.de> writes:
> So putting check_mul_overflow_size_t() into malloc-internal.h is
> preferred over malloc-private.h?

Well, that's *my* opinion.  Others may vary ;-)

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v5] Add reallocarray function.
  2017-05-10 13:03       ` [PATCH v4] " Dennis Wölfing
  2017-05-10 21:29         ` DJ Delorie
@ 2017-05-15 12:22         ` Dennis Wölfing
  2017-05-22 14:16           ` Dennis Wölfing
  1 sibling, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-15 12:22 UTC (permalink / raw)
  To: libc-alpha

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on i686 and x86_64.

2017-05-15  Dennis Wölfing  <denniswoelfing@gmx.de>
            Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* include/stdlib.h (__libc_reallocarray): New declaration.
	* malloc/Makefile (routines): Add reallocarray.
	(tests): Add tst-reallocarray.c.
	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/malloc-internal.h (check_mul_overflow_size_t): New inline
	function.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/reallocarray.c: New file.
	* malloc/tst-reallocarray.c: New test file.
	* manual/memory.texi: Document reallocarray.
	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
---
 NEWS                                               |   2 +
 include/stdlib.h                                   |   4 +
 malloc/Makefile                                    |   4 +-
 malloc/Versions                                    |   4 +
 malloc/malloc-internal.h                           |  19 ++++
 malloc/malloc.h                                    |   8 ++
 malloc/reallocarray.c                              |  37 +++++++
 malloc/tst-reallocarray.c                          | 119 +++++++++++++++++++++
 manual/memory.texi                                 |  44 ++++++--
 stdlib/stdlib.h                                    |  11 ++
 sysdeps/arm/nacl/libc.abilist                      |   2 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   2 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   2 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   2 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   2 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   2 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   2 +
 39 files changed, 298 insertions(+), 12 deletions(-)
 create mode 100644 malloc/reallocarray.c
 create mode 100644 malloc/tst-reallocarray.c

diff --git a/NEWS b/NEWS
index 09c302b642..236bbc591f 100644
--- a/NEWS
+++ b/NEWS
@@ -63,6 +63,8 @@ Version 2.26
 
 * The obsolete <sys/ultrasound.h> header file has been removed.
 
+* The reallocarray function has been added to libc.
+
 Security related changes:
 
 * The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes,
diff --git a/include/stdlib.h b/include/stdlib.h
index c3ee680bd6..5847445fd3 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -110,6 +110,10 @@ extern int __posix_memalign (void **memptr, size_t alignment, size_t size);
 extern void *__libc_memalign (size_t alignment, size_t size)
      __attribute_malloc__;
 
+extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+libc_hidden_proto (__libc_reallocarray)
+
 extern int __libc_system (const char *line);
 
 
diff --git a/malloc/Makefile b/malloc/Makefile
index d0f23f7bf3..b7d4c63920 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
@@ -49,7 +49,7 @@ endif
 tests += $(tests-static)
 test-srcs = tst-mtrace
 
-routines = malloc morecore mcheck mtrace obstack \
+routines = malloc morecore mcheck mtrace obstack reallocarray \
   scratch_buffer_grow scratch_buffer_grow_preserve \
   scratch_buffer_set_array_size
 
diff --git a/malloc/Versions b/malloc/Versions
index e34ab177be..23aafb5ccc 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -62,6 +62,7 @@ libc {
     aligned_alloc;
   }
   GLIBC_2.26 {
+    reallocarray;
   }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
@@ -74,5 +75,8 @@ libc {
     __libc_scratch_buffer_grow;
     __libc_scratch_buffer_grow_preserve;
     __libc_scratch_buffer_set_array_size;
+
+    # Internal name for reallocarray
+    __libc_reallocarray;
   }
 }
diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index de6103d7e1..dbd801a58e 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -81,5 +81,24 @@ void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
 /* Called in the child process after a fork.  */
 void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
 
+/* Set *RESULT to LEFT * RIGHT.  Return true if the multiplication
+   overflowed.  */
+static inline bool
+check_mul_overflow_size_t (size_t left, size_t right, size_t *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow (left, right, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = left * right;
+  size_t half_size_t = ((size_t) 1) << (8 * sizeof (size_t) / 2);
+  if (__glibc_unlikely ((left | right) >= half_size_t))
+    {
+      if (__glibc_unlikely (right != 0 && *result / right != left))
+        return true;
+    }
+  return false;
+#endif
+}
 
 #endif /* _MALLOC_INTERNAL_H */
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 274c0958e4..339ab64c7d 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+__THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
new file mode 100644
index 0000000000..07562c30c9
--- /dev/null
+++ b/malloc/reallocarray.c
@@ -0,0 +1,37 @@
+/* Change the size of an allocated block.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <malloc/malloc-internal.h>
+
+void *
+__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
+{
+  size_t bytes;
+  if (check_mul_overflow_size_t (nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return realloc (optr, bytes);
+}
+libc_hidden_def (__libc_reallocarray)
+
+weak_alias (__libc_reallocarray, reallocarray)
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..e914e2938b
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,119 @@
+/* Test for reallocarray.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray (NULL, 10, 2);
+  TEST_VERIFY_EXIT (ptr);
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 10*2);
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray (ptr, 20, 2);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY (malloc_usable_size (ptr) >= 20*2);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray (ptr, 5, 3);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 5*3);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 2, ~(size_t)0);
+  TEST_VERIFY (!ptr2);
+  TEST_VERIFY (errno == ENOMEM);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  free (ptr);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/manual/memory.texi b/manual/memory.texi
index a256ca07b2..0764ce1d22 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -751,8 +751,8 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
 @comment malloc.h stdlib.h
@@ -816,9 +816,27 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
-Like @code{malloc}, @code{realloc} may return a null pointer if no
-memory space is available to make the block bigger.  When this happens,
-the original block is untouched; it has not been modified or relocated.
+@comment malloc.h stdlib.h
+@comment BSD
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails if the
+multiplication overflows.  If the multiplication does overflow,
+@code{reallocarray} sets @code{errno} to @code{ENOMEM} and returns a null
+pointer and the original block remains unchanged.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+@end deftypefun
+
+Like @code{malloc}, @code{realloc} and @code{reallocarray} may return a null
+pointer if no memory space is available to make the block bigger.  When this
+happens, the original block is untouched; it has not been modified or
+relocated.
 
 In most cases it makes no difference what happens to the original block
 when @code{realloc} fails, because the application program cannot continue
@@ -838,16 +856,17 @@ xrealloc (void *ptr, size_t size)
 @}
 @end smallexample
 
-You can also use @code{realloc} to make a block smaller.  The reason you
-would do this is to avoid tying up a lot of memory space when only a little
-is needed.
+You can also use @code{realloc} or @code{reallocarray} to make a block
+smaller.  The reason you would do this is to avoid tying up a lot of memory
+space when only a little is needed.
 @comment The following is no longer true with the new malloc.
 @comment But it seems wise to keep the warning for other implementations.
 In several allocation implementations, making a block smaller sometimes
 necessitates copying it, so it can fail if no other space is available.
 
-If the new size you specify is the same as the old size, @code{realloc}
-is guaranteed to change nothing and return the same address that you gave.
+If the new size you specify is the same as the old size, @code{realloc} and
+@code{reallocarray} are guaranteed to change nothing and return the same
+address that you gave.
 
 @node Allocating Cleared Space
 @subsubsection Allocating Cleared Space
@@ -1588,6 +1607,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 99125f2d23..428ca2ef68 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index abd70c8108..b60bf7049a 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1853,3 +1853,5 @@ GLIBC_2.25 gnu_dev_minor F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..a494c3947d 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..2fc1a9bae7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..4465a62ff1 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..96126d9e6a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..aae351bbff 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..81ec65bec0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..9db205b68e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..ee59e950b6 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..feb869757c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..a5b1c42929 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..570a859aac 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..71008ad873 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..1a07d66caf 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..a62a41be62 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..f4f11dc625 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..2977569f2c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..271d32e19b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..372ef67c27 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..705ff851a9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..21fd2b5671 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..313a71e589 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..94a4fb2213 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..6db5811c3f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..ce14ceb15f 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..f69de7aa83 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..a330855308 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
-- 
2.12.2

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v5] Add reallocarray function.
  2017-05-15 12:22         ` [PATCH v5] " Dennis Wölfing
@ 2017-05-22 14:16           ` Dennis Wölfing
  2017-05-22 18:24             ` DJ Delorie
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-22 14:16 UTC (permalink / raw)
  To: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 3257 bytes --]

On 15.05.2017 14:22, Dennis Wölfing wrote:
> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
> 
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
> 
> Tested on i686 and x86_64.
> 
> 2017-05-15  Dennis Wölfing  <denniswoelfing@gmx.de>
>             Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
> 
> 	* include/stdlib.h (__libc_reallocarray): New declaration.
> 	* malloc/Makefile (routines): Add reallocarray.
> 	(tests): Add tst-reallocarray.c.
> 	* malloc/Versions: Add reallocarray and __libc_reallocarray.
> 	* malloc/malloc-internal.h (check_mul_overflow_size_t): New inline
> 	function.
> 	* malloc/malloc.h (reallocarray): New declaration.
> 	* stdlib/stdlib.h (reallocarray): Likewise.
> 	* malloc/reallocarray.c: New file.
> 	* malloc/tst-reallocarray.c: New test file.
> 	* manual/memory.texi: Document reallocarray.
> 	* sysdeps/arm/nacl/libc.abilist: Add reallocarray.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

Ping. Note that because of the removal of the NaCl port the
sysdeps/arm/nacl/libc.abilist file must no longer be patched.
I have attached a rebased version of the patch. Otherwise the patch is
identical the the v5.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: reallocarray.patch --]
[-- Type: text/x-patch; name="reallocarray.patch", Size: 30044 bytes --]

Add reallocarray function.

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on i686 and x86_64.

2017-05-22  Dennis Wölfing  <denniswoelfing@gmx.de>
            Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* include/stdlib.h (__libc_reallocarray): New declaration.
	* malloc/Makefile (routines): Add reallocarray.
	(tests): Add tst-reallocarray.c.
	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/malloc-internal.h (check_mul_overflow_size_t): New inline
	function.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/reallocarray.c: New file.
	* malloc/tst-reallocarray.c: New test file.
	* manual/memory.texi: Document reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

diff --git a/NEWS b/NEWS
index b4ecd6201d..e70bff01db 100644
--- a/NEWS
+++ b/NEWS
@@ -66,6 +66,8 @@ Version 2.26
 * The port to Native Client running on ARMv7-A (--host=arm-nacl) has been
   removed.
 
+* The reallocarray function has been added to libc.
+
 Security related changes:
 
 * The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes,
diff --git a/include/stdlib.h b/include/stdlib.h
index c3ee680bd6..5847445fd3 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -110,6 +110,10 @@ extern int __posix_memalign (void **memptr, size_t alignment, size_t size);
 extern void *__libc_memalign (size_t alignment, size_t size)
      __attribute_malloc__;
 
+extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+libc_hidden_proto (__libc_reallocarray)
+
 extern int __libc_system (const char *line);
 
 
diff --git a/malloc/Makefile b/malloc/Makefile
index d0f23f7bf3..b7d4c63920 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
@@ -49,7 +49,7 @@ endif
 tests += $(tests-static)
 test-srcs = tst-mtrace
 
-routines = malloc morecore mcheck mtrace obstack \
+routines = malloc morecore mcheck mtrace obstack reallocarray \
   scratch_buffer_grow scratch_buffer_grow_preserve \
   scratch_buffer_set_array_size
 
diff --git a/malloc/Versions b/malloc/Versions
index e34ab177be..23aafb5ccc 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -62,6 +62,7 @@ libc {
     aligned_alloc;
   }
   GLIBC_2.26 {
+    reallocarray;
   }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
@@ -74,5 +75,8 @@ libc {
     __libc_scratch_buffer_grow;
     __libc_scratch_buffer_grow_preserve;
     __libc_scratch_buffer_set_array_size;
+
+    # Internal name for reallocarray
+    __libc_reallocarray;
   }
 }
diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index de6103d7e1..dbd801a58e 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -81,5 +81,24 @@ void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
 /* Called in the child process after a fork.  */
 void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
 
+/* Set *RESULT to LEFT * RIGHT.  Return true if the multiplication
+   overflowed.  */
+static inline bool
+check_mul_overflow_size_t (size_t left, size_t right, size_t *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow (left, right, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = left * right;
+  size_t half_size_t = ((size_t) 1) << (8 * sizeof (size_t) / 2);
+  if (__glibc_unlikely ((left | right) >= half_size_t))
+    {
+      if (__glibc_unlikely (right != 0 && *result / right != left))
+        return true;
+    }
+  return false;
+#endif
+}
 
 #endif /* _MALLOC_INTERNAL_H */
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 274c0958e4..339ab64c7d 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+__THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
new file mode 100644
index 0000000000..07562c30c9
--- /dev/null
+++ b/malloc/reallocarray.c
@@ -0,0 +1,37 @@
+/* Change the size of an allocated block.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <malloc/malloc-internal.h>
+
+void *
+__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
+{
+  size_t bytes;
+  if (check_mul_overflow_size_t (nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return realloc (optr, bytes);
+}
+libc_hidden_def (__libc_reallocarray)
+
+weak_alias (__libc_reallocarray, reallocarray)
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..e914e2938b
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,119 @@
+/* Test for reallocarray.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray (NULL, 10, 2);
+  TEST_VERIFY_EXIT (ptr);
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 10*2);
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray (ptr, 20, 2);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY (malloc_usable_size (ptr) >= 20*2);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray (ptr, 5, 3);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 5*3);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 2, ~(size_t)0);
+  TEST_VERIFY (!ptr2);
+  TEST_VERIFY (errno == ENOMEM);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  free (ptr);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/manual/memory.texi b/manual/memory.texi
index a256ca07b2..0764ce1d22 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -751,8 +751,8 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
 @comment malloc.h stdlib.h
@@ -816,9 +816,27 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
-Like @code{malloc}, @code{realloc} may return a null pointer if no
-memory space is available to make the block bigger.  When this happens,
-the original block is untouched; it has not been modified or relocated.
+@comment malloc.h stdlib.h
+@comment BSD
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails if the
+multiplication overflows.  If the multiplication does overflow,
+@code{reallocarray} sets @code{errno} to @code{ENOMEM} and returns a null
+pointer and the original block remains unchanged.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+@end deftypefun
+
+Like @code{malloc}, @code{realloc} and @code{reallocarray} may return a null
+pointer if no memory space is available to make the block bigger.  When this
+happens, the original block is untouched; it has not been modified or
+relocated.
 
 In most cases it makes no difference what happens to the original block
 when @code{realloc} fails, because the application program cannot continue
@@ -838,16 +856,17 @@ xrealloc (void *ptr, size_t size)
 @}
 @end smallexample
 
-You can also use @code{realloc} to make a block smaller.  The reason you
-would do this is to avoid tying up a lot of memory space when only a little
-is needed.
+You can also use @code{realloc} or @code{reallocarray} to make a block
+smaller.  The reason you would do this is to avoid tying up a lot of memory
+space when only a little is needed.
 @comment The following is no longer true with the new malloc.
 @comment But it seems wise to keep the warning for other implementations.
 In several allocation implementations, making a block smaller sometimes
 necessitates copying it, so it can fail if no other space is available.
 
-If the new size you specify is the same as the old size, @code{realloc}
-is guaranteed to change nothing and return the same address that you gave.
+If the new size you specify is the same as the old size, @code{realloc} and
+@code{reallocarray} are guaranteed to change nothing and return the same
+address that you gave.
 
 @node Allocating Cleared Space
 @subsubsection Allocating Cleared Space
@@ -1588,6 +1607,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 99125f2d23..428ca2ef68 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..a494c3947d 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..2fc1a9bae7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..4465a62ff1 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..96126d9e6a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..aae351bbff 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..81ec65bec0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..9db205b68e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..ee59e950b6 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..feb869757c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..a5b1c42929 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..570a859aac 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..71008ad873 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..1a07d66caf 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..a62a41be62 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..f4f11dc625 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..2977569f2c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..271d32e19b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..372ef67c27 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..705ff851a9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..21fd2b5671 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..313a71e589 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..94a4fb2213 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..6db5811c3f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..ce14ceb15f 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..f69de7aa83 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..a330855308 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v5] Add reallocarray function.
  2017-05-22 14:16           ` Dennis Wölfing
@ 2017-05-22 18:24             ` DJ Delorie
  2017-05-22 18:51               ` Zack Weinberg
  0 siblings, 1 reply; 48+ messages in thread
From: DJ Delorie @ 2017-05-22 18:24 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha


I'm OK with this version.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v5] Add reallocarray function.
  2017-05-22 18:24             ` DJ Delorie
@ 2017-05-22 18:51               ` Zack Weinberg
  2017-05-22 20:25                 ` [PATCH v6] " Dennis Wölfing
  0 siblings, 1 reply; 48+ messages in thread
From: Zack Weinberg @ 2017-05-22 18:51 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: GNU C Library

Looks good to me, except for two things in the documentation:

> +... except that @code{reallocarray} fails if the
> +multiplication overflows.  If the multiplication does overflow,
> +@code{reallocarray} sets @code{errno} to @code{ENOMEM} and returns
> +a null pointer and the original block remains unchanged.

First, this is repeating itself.  I suggest instead

  ... except that @code{reallocarray} fails safely if the the
  multiplication overflows, by setting @code{errno} to @code{ENOMEM},
  returning a null pointer, and leaving the original block unchanged.

> +@code{reallocarray} should be used instead of @code{realloc} when the new size
> +of the allocated block is the result of a multiplication that might overflow.
> +@end deftypefun

Second, we don't have automatic generation of portability notes yet,
so you need to write one by hand:

  @code{reallocarray} should be used instead of @code{realloc} when
  the new size of the allocated block is the result of a
  multiplication that might overflow.

  @strong{Portability Note:} This function is not part of any
  standard.  It was first introduced in OpenBSD 5.6.
  @end deftypefun

zw

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v6] Add reallocarray function.
  2017-05-22 18:51               ` Zack Weinberg
@ 2017-05-22 20:25                 ` Dennis Wölfing
  2017-05-29 12:29                   ` Dennis Wölfing
  2017-05-30 15:17                   ` [PATCH v6] " Adhemerval Zanella
  0 siblings, 2 replies; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-22 20:25 UTC (permalink / raw)
  To: libc-alpha; +Cc: zackw

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on i686 and x86_64.

2017-05-22  Dennis Wölfing  <denniswoelfing@gmx.de>
            Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* include/stdlib.h (__libc_reallocarray): New declaration.
	* malloc/Makefile (routines): Add reallocarray.
	(tests): Add tst-reallocarray.c.
	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/malloc-internal.h (check_mul_overflow_size_t): New inline
	function.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/reallocarray.c: New file.
	* malloc/tst-reallocarray.c: New test file.
	* manual/memory.texi: Document reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
---
 NEWS                                               |   2 +
 include/stdlib.h                                   |   4 +
 malloc/Makefile                                    |   4 +-
 malloc/Versions                                    |   4 +
 malloc/malloc-internal.h                           |  19 ++++
 malloc/malloc.h                                    |   8 ++
 malloc/reallocarray.c                              |  37 +++++++
 malloc/tst-reallocarray.c                          | 119 +++++++++++++++++++++
 manual/memory.texi                                 |  46 ++++++--
 stdlib/stdlib.h                                    |  11 ++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   2 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   2 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   2 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   2 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   2 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   2 +
 38 files changed, 298 insertions(+), 12 deletions(-)
 create mode 100644 malloc/reallocarray.c
 create mode 100644 malloc/tst-reallocarray.c

diff --git a/NEWS b/NEWS
index b4ecd6201d..e70bff01db 100644
--- a/NEWS
+++ b/NEWS
@@ -66,6 +66,8 @@ Version 2.26
 * The port to Native Client running on ARMv7-A (--host=arm-nacl) has been
   removed.
 
+* The reallocarray function has been added to libc.
+
 Security related changes:
 
 * The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes,
diff --git a/include/stdlib.h b/include/stdlib.h
index c3ee680bd6..5847445fd3 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -110,6 +110,10 @@ extern int __posix_memalign (void **memptr, size_t alignment, size_t size);
 extern void *__libc_memalign (size_t alignment, size_t size)
      __attribute_malloc__;
 
+extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+libc_hidden_proto (__libc_reallocarray)
+
 extern int __libc_system (const char *line);
 
 
diff --git a/malloc/Makefile b/malloc/Makefile
index d0f23f7bf3..b7d4c63920 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
@@ -49,7 +49,7 @@ endif
 tests += $(tests-static)
 test-srcs = tst-mtrace
 
-routines = malloc morecore mcheck mtrace obstack \
+routines = malloc morecore mcheck mtrace obstack reallocarray \
   scratch_buffer_grow scratch_buffer_grow_preserve \
   scratch_buffer_set_array_size
 
diff --git a/malloc/Versions b/malloc/Versions
index e34ab177be..23aafb5ccc 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -62,6 +62,7 @@ libc {
     aligned_alloc;
   }
   GLIBC_2.26 {
+    reallocarray;
   }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
@@ -74,5 +75,8 @@ libc {
     __libc_scratch_buffer_grow;
     __libc_scratch_buffer_grow_preserve;
     __libc_scratch_buffer_set_array_size;
+
+    # Internal name for reallocarray
+    __libc_reallocarray;
   }
 }
diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index de6103d7e1..dbd801a58e 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -81,5 +81,24 @@ void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
 /* Called in the child process after a fork.  */
 void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
 
+/* Set *RESULT to LEFT * RIGHT.  Return true if the multiplication
+   overflowed.  */
+static inline bool
+check_mul_overflow_size_t (size_t left, size_t right, size_t *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow (left, right, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = left * right;
+  size_t half_size_t = ((size_t) 1) << (8 * sizeof (size_t) / 2);
+  if (__glibc_unlikely ((left | right) >= half_size_t))
+    {
+      if (__glibc_unlikely (right != 0 && *result / right != left))
+        return true;
+    }
+  return false;
+#endif
+}
 
 #endif /* _MALLOC_INTERNAL_H */
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 274c0958e4..339ab64c7d 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+__THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
new file mode 100644
index 0000000000..07562c30c9
--- /dev/null
+++ b/malloc/reallocarray.c
@@ -0,0 +1,37 @@
+/* Change the size of an allocated block.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <malloc/malloc-internal.h>
+
+void *
+__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
+{
+  size_t bytes;
+  if (check_mul_overflow_size_t (nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return realloc (optr, bytes);
+}
+libc_hidden_def (__libc_reallocarray)
+
+weak_alias (__libc_reallocarray, reallocarray)
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..e914e2938b
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,119 @@
+/* Test for reallocarray.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray (NULL, 10, 2);
+  TEST_VERIFY_EXIT (ptr);
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 10*2);
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray (ptr, 20, 2);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY (malloc_usable_size (ptr) >= 20*2);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray (ptr, 5, 3);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 5*3);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 2, ~(size_t)0);
+  TEST_VERIFY (!ptr2);
+  TEST_VERIFY (errno == ENOMEM);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  free (ptr);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/manual/memory.texi b/manual/memory.texi
index a256ca07b2..fb6b594ef1 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -751,8 +751,8 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
 @comment malloc.h stdlib.h
@@ -816,9 +816,29 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
-Like @code{malloc}, @code{realloc} may return a null pointer if no
-memory space is available to make the block bigger.  When this happens,
-the original block is untouched; it has not been modified or relocated.
+@comment malloc.h stdlib.h
+@comment BSD
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails safely if
+the multiplication overflows, by setting @code{errno} to @code{ENOMEM},
+returning a null pointer, and leaving the original block unchanged.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+
+@strong{Portability Note:} This function is not part of any standard.  It was
+first introduced in OpenBSD 5.6.
+@end deftypefun
+
+Like @code{malloc}, @code{realloc} and @code{reallocarray} may return a null
+pointer if no memory space is available to make the block bigger.  When this
+happens, the original block is untouched; it has not been modified or
+relocated.
 
 In most cases it makes no difference what happens to the original block
 when @code{realloc} fails, because the application program cannot continue
@@ -838,16 +858,17 @@ xrealloc (void *ptr, size_t size)
 @}
 @end smallexample
 
-You can also use @code{realloc} to make a block smaller.  The reason you
-would do this is to avoid tying up a lot of memory space when only a little
-is needed.
+You can also use @code{realloc} or @code{reallocarray} to make a block
+smaller.  The reason you would do this is to avoid tying up a lot of memory
+space when only a little is needed.
 @comment The following is no longer true with the new malloc.
 @comment But it seems wise to keep the warning for other implementations.
 In several allocation implementations, making a block smaller sometimes
 necessitates copying it, so it can fail if no other space is available.
 
-If the new size you specify is the same as the old size, @code{realloc}
-is guaranteed to change nothing and return the same address that you gave.
+If the new size you specify is the same as the old size, @code{realloc} and
+@code{reallocarray} are guaranteed to change nothing and return the same
+address that you gave.
 
 @node Allocating Cleared Space
 @subsubsection Allocating Cleared Space
@@ -1588,6 +1609,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 99125f2d23..428ca2ef68 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..a494c3947d 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..2fc1a9bae7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..4465a62ff1 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..96126d9e6a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..aae351bbff 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..81ec65bec0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..9db205b68e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..ee59e950b6 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..feb869757c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..a5b1c42929 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..570a859aac 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..71008ad873 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..1a07d66caf 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..a62a41be62 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..f4f11dc625 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..2977569f2c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..271d32e19b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..372ef67c27 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..705ff851a9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..21fd2b5671 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..313a71e589 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..94a4fb2213 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..6db5811c3f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..ce14ceb15f 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..f69de7aa83 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..a330855308 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
-- 
2.12.2

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-22 20:25                 ` [PATCH v6] " Dennis Wölfing
@ 2017-05-29 12:29                   ` Dennis Wölfing
  2017-05-30 16:02                     ` DJ Delorie
  2017-05-30 15:17                   ` [PATCH v6] " Adhemerval Zanella
  1 sibling, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-29 12:29 UTC (permalink / raw)
  To: libc-alpha; +Cc: zackw

On 22.05.2017 22:25, Dennis Wölfing wrote:
> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
> 
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
> 
> Tested on i686 and x86_64.
> 
> 2017-05-22  Dennis Wölfing  <denniswoelfing@gmx.de>
>             Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
> 
> 	* include/stdlib.h (__libc_reallocarray): New declaration.
> 	* malloc/Makefile (routines): Add reallocarray.
> 	(tests): Add tst-reallocarray.c.
> 	* malloc/Versions: Add reallocarray and __libc_reallocarray.
> 	* malloc/malloc-internal.h (check_mul_overflow_size_t): New inline
> 	function.
> 	* malloc/malloc.h (reallocarray): New declaration.
> 	* stdlib/stdlib.h (reallocarray): Likewise.
> 	* malloc/reallocarray.c: New file.
> 	* malloc/tst-reallocarray.c: New test file.
> 	* manual/memory.texi: Document reallocarray.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Add reallocarray.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

Ping

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-22 20:25                 ` [PATCH v6] " Dennis Wölfing
  2017-05-29 12:29                   ` Dennis Wölfing
@ 2017-05-30 15:17                   ` Adhemerval Zanella
  2017-05-30 20:02                     ` Dennis Wölfing
  1 sibling, 1 reply; 48+ messages in thread
From: Adhemerval Zanella @ 2017-05-30 15:17 UTC (permalink / raw)
  To: libc-alpha

On 22/05/2017 17:25, Dennis Wölfing wrote:
> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
> 
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
> 
> Tested on i686 and x86_64.
> 
> 2017-05-22  Dennis Wölfing  <denniswoelfing@gmx.de>
>             Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
> 
> 	* include/stdlib.h (__libc_reallocarray): New declaration.
> 	* malloc/Makefile (routines): Add reallocarray.
> 	(tests): Add tst-reallocarray.c.
> 	* malloc/Versions: Add reallocarray and __libc_reallocarray.
> 	* malloc/malloc-internal.h (check_mul_overflow_size_t): New inline
> 	function.
> 	* malloc/malloc.h (reallocarray): New declaration.
> 	* stdlib/stdlib.h (reallocarray): Likewise.
> 	* malloc/reallocarray.c: New file.
> 	* malloc/tst-reallocarray.c: New test file.
> 	* manual/memory.texi: Document reallocarray.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Add reallocarray.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

LGTM with some nits below.

> diff --git a/NEWS b/NEWS
> index b4ecd6201d..e70bff01db 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -66,6 +66,8 @@ Version 2.26
>  * The port to Native Client running on ARMv7-A (--host=arm-nacl) has been
>    removed.
>  
> +* The reallocarray function has been added to libc.
> +
>  Security related changes:

I would extend it a bit by describing what reallocarray is intended to
(maybe something as 'It is a realloc replacement with a check for integer
overflow when calculating total allocation size').

> diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
> new file mode 100644
> index 0000000000..e914e2938b
> --- /dev/null
> +++ b/malloc/tst-reallocarray.c
> @@ -0,0 +1,119 @@
> +/* Test for reallocarray.
> +   Copyright (C) 2014-2017 Free Software Foundation, Inc.

It is a new file, so use 2017 instead.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <support/check.h>
> +
> +static int
> +do_test (void)
> +

Extra line.

> diff --git a/manual/memory.texi b/manual/memory.texi
> index a256ca07b2..fb6b594ef1 100644
> --- a/manual/memory.texi
> +++ b/manual/memory.texi
> @@ -751,8 +751,8 @@ be a buffer that you use to hold a line being read from a file; no matter
>  how long you make the buffer initially, you may encounter a line that is
>  longer.
>  
> -You can make the block longer by calling @code{realloc}.  This function
> -is declared in @file{stdlib.h}.
> +You can make the block longer by calling @code{realloc} or
> +@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
>  @pindex stdlib.h
>  
>  @comment malloc.h stdlib.h
> @@ -816,9 +816,29 @@ behavior, and will probably crash when @code{realloc} is passed a null
>  pointer.
>  @end deftypefun
>  
> -Like @code{malloc}, @code{realloc} may return a null pointer if no
> -memory space is available to make the block bigger.  When this happens,
> -the original block is untouched; it has not been modified or relocated.
> +@comment malloc.h stdlib.h
> +@comment BSD
> +@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
> +
> +The @code{reallocarray} function changes the size of the block whose address
> +is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
> +each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
> +@var{nmemb} * @var{size})}, except that @code{reallocarray} fails safely if
> +the multiplication overflows, by setting @code{errno} to @code{ENOMEM},
> +returning a null pointer, and leaving the original block unchanged.
> +
> +@code{reallocarray} should be used instead of @code{realloc} when the new size
> +of the allocated block is the result of a multiplication that might overflow.
> +
> +@strong{Portability Note:} This function is not part of any standard.  It was
> +first introduced in OpenBSD 5.6.
> +@end deftypefun

I think it is worth to add FreeBSD 11.0 also supports it.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-29 12:29                   ` Dennis Wölfing
@ 2017-05-30 16:02                     ` DJ Delorie
  2017-05-30 16:17                       ` Zack Weinberg
  0 siblings, 1 reply; 48+ messages in thread
From: DJ Delorie @ 2017-05-30 16:02 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha


I have no further objections to this patch...

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 16:02                     ` DJ Delorie
@ 2017-05-30 16:17                       ` Zack Weinberg
  2017-05-30 20:02                         ` Dennis Wölfing
  0 siblings, 1 reply; 48+ messages in thread
From: Zack Weinberg @ 2017-05-30 16:17 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: GNU C Library

Thumbs up from me, too.  Dennis, do you need someone to commit the
patch for you?

zw

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 16:17                       ` Zack Weinberg
@ 2017-05-30 20:02                         ` Dennis Wölfing
  2017-05-30 20:35                           ` Adhemerval Zanella
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-30 20:02 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

On 30.05.2017 18:17, Zack Weinberg wrote:
> Thumbs up from me, too.  Dennis, do you need someone to commit the
> patch for you?

Yes, I don't have commit access. But I will first address the issues
Adhemerval Zanella pointed out and send an updated patch.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 15:17                   ` [PATCH v6] " Adhemerval Zanella
@ 2017-05-30 20:02                     ` Dennis Wölfing
  2017-05-30 20:16                       ` Florian Weimer
  2017-05-30 20:27                       ` Adhemerval Zanella
  0 siblings, 2 replies; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-30 20:02 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On 30.05.2017 17:17, Adhemerval Zanella wrote:
>> +@strong{Portability Note:} This function is not part of any standard.  It was
>> +first introduced in OpenBSD 5.6.
>> +@end deftypefun
> 
> I think it is worth to add FreeBSD 11.0 also supports it.

I'm not sure about that. It makes sense to mention OpenBSD because that
is where reallocarray originates from. But FreeBSD is not the only other
OS that implements reallocarray. If we mention FreeBSD do we also
mention NetBSD and any other implementation?
I would prefer to leave that sentence as it is.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 20:02                     ` Dennis Wölfing
@ 2017-05-30 20:16                       ` Florian Weimer
  2017-05-30 20:27                       ` Adhemerval Zanella
  1 sibling, 0 replies; 48+ messages in thread
From: Florian Weimer @ 2017-05-30 20:16 UTC (permalink / raw)
  To: Dennis Wölfing
  Cc: Adhemerval Zanella, libc-alpha@sourceware.org >> GNU C Library

On 05/30/2017 10:02 PM, Dennis Wölfing wrote:
> On 30.05.2017 17:17, Adhemerval Zanella wrote:
>>> +@strong{Portability Note:} This function is not part of any standard.  It was
>>> +first introduced in OpenBSD 5.6.
>>> +@end deftypefun
>>
>> I think it is worth to add FreeBSD 11.0 also supports it.
> 
> I'm not sure about that. It makes sense to mention OpenBSD because that
> is where reallocarray originates from. But FreeBSD is not the only other
> OS that implements reallocarray. If we mention FreeBSD do we also
> mention NetBSD and any other implementation?
> I would prefer to leave that sentence as it is.

For what it's worth, I agree with you.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 20:02                     ` Dennis Wölfing
  2017-05-30 20:16                       ` Florian Weimer
@ 2017-05-30 20:27                       ` Adhemerval Zanella
  1 sibling, 0 replies; 48+ messages in thread
From: Adhemerval Zanella @ 2017-05-30 20:27 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha



On 30/05/2017 17:02, Dennis Wölfing wrote:
> On 30.05.2017 17:17, Adhemerval Zanella wrote:
>>> +@strong{Portability Note:} This function is not part of any standard.  It was
>>> +first introduced in OpenBSD 5.6.
>>> +@end deftypefun
>>
>> I think it is worth to add FreeBSD 11.0 also supports it.
> 
> I'm not sure about that. It makes sense to mention OpenBSD because that
> is where reallocarray originates from. But FreeBSD is not the only other
> OS that implements reallocarray. If we mention FreeBSD do we also
> mention NetBSD and any other implementation?
> I would prefer to leave that sentence as it is.

Fair enough.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 20:02                         ` Dennis Wölfing
@ 2017-05-30 20:35                           ` Adhemerval Zanella
  2017-05-30 20:38                             ` Dennis Wölfing
  0 siblings, 1 reply; 48+ messages in thread
From: Adhemerval Zanella @ 2017-05-30 20:35 UTC (permalink / raw)
  To: libc-alpha



On 30/05/2017 17:02, Dennis Wölfing wrote:
> On 30.05.2017 18:17, Zack Weinberg wrote:
>> Thumbs up from me, too.  Dennis, do you need someone to commit the
>> patch for you?
> 
> Yes, I don't have commit access. But I will first address the issues
> Adhemerval Zanella pointed out and send an updated patch.
> 

If you have commit access you can just fix the small issues I pointed
out and push upstream (no need to resend a new version).

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 20:35                           ` Adhemerval Zanella
@ 2017-05-30 20:38                             ` Dennis Wölfing
  2017-05-30 20:40                               ` Adhemerval Zanella
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-30 20:38 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On 30.05.2017 22:35, Adhemerval Zanella wrote:
> On 30/05/2017 17:02, Dennis Wölfing wrote:
>> On 30.05.2017 18:17, Zack Weinberg wrote:
>>> Thumbs up from me, too.  Dennis, do you need someone to commit the
>>> patch for you?
>>
>> Yes, I don't have commit access. But I will first address the issues
>> Adhemerval Zanella pointed out and send an updated patch.
>>
> 
> If you have commit access you can just fix the small issues I pointed
> out and push upstream (no need to resend a new version).
> 

I think you misunderstood me. The "Yes" referred to the question whether
I need someone else to commit it. I don't have commit access.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v6] Add reallocarray function.
  2017-05-30 20:38                             ` Dennis Wölfing
@ 2017-05-30 20:40                               ` Adhemerval Zanella
  2017-05-30 20:50                                 ` [PATCH v7] " Dennis Wölfing
  0 siblings, 1 reply; 48+ messages in thread
From: Adhemerval Zanella @ 2017-05-30 20:40 UTC (permalink / raw)
  To: Dennis Wölfing; +Cc: libc-alpha



On 30/05/2017 17:39, Dennis Wölfing wrote:
> On 30.05.2017 22:35, Adhemerval Zanella wrote:
>> On 30/05/2017 17:02, Dennis Wölfing wrote:
>>> On 30.05.2017 18:17, Zack Weinberg wrote:
>>>> Thumbs up from me, too.  Dennis, do you need someone to commit the
>>>> patch for you?
>>>
>>> Yes, I don't have commit access. But I will first address the issues
>>> Adhemerval Zanella pointed out and send an updated patch.
>>>
>>
>> If you have commit access you can just fix the small issues I pointed
>> out and push upstream (no need to resend a new version).
>>
> 
> I think you misunderstood me. The "Yes" referred to the question whether
> I need someone else to commit it. I don't have commit access.
> 

Alright, when you post the new version I can push it upstream for you.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7] Add reallocarray function.
  2017-05-30 20:40                               ` Adhemerval Zanella
@ 2017-05-30 20:50                                 ` Dennis Wölfing
  2017-05-30 22:06                                   ` Adhemerval Zanella
  0 siblings, 1 reply; 48+ messages in thread
From: Dennis Wölfing @ 2017-05-30 20:50 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella

The reallocarray function is an extension from OpenBSD.  It is an
integer-overflow-safe replacement for realloc(p, X*Y) and
malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
certain security issues in code.

This is an updated version of a patch originally submitted by Rüdiger
Sonderfeld in May 2014.
See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.

Tested on i686 and x86_64.

2017-05-30  Dennis Wölfing  <denniswoelfing@gmx.de>
            Rüdiger Sonderfeld  <ruediger@c-plusplus.de>

	* include/stdlib.h (__libc_reallocarray): New declaration.
	* malloc/Makefile (routines): Add reallocarray.
	(tests): Add tst-reallocarray.c.
	* malloc/Versions: Add reallocarray and __libc_reallocarray.
	* malloc/malloc-internal.h (check_mul_overflow_size_t): New inline
	function.
	* malloc/malloc.h (reallocarray): New declaration.
	* stdlib/stdlib.h (reallocarray): Likewise.
	* malloc/reallocarray.c: New file.
	* malloc/tst-reallocarray.c: New test file.
	* manual/memory.texi: Document reallocarray.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Add reallocarray.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
---
 NEWS                                               |   4 +
 include/stdlib.h                                   |   4 +
 malloc/Makefile                                    |   4 +-
 malloc/Versions                                    |   4 +
 malloc/malloc-internal.h                           |  19 ++++
 malloc/malloc.h                                    |   8 ++
 malloc/reallocarray.c                              |  37 +++++++
 malloc/tst-reallocarray.c                          | 118 +++++++++++++++++++++
 manual/memory.texi                                 |  46 ++++++--
 stdlib/stdlib.h                                    |  11 ++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   2 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   2 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   2 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   2 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   2 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   2 +
 38 files changed, 299 insertions(+), 12 deletions(-)
 create mode 100644 malloc/reallocarray.c
 create mode 100644 malloc/tst-reallocarray.c

diff --git a/NEWS b/NEWS
index b4ecd6201d..f92392a3f8 100644
--- a/NEWS
+++ b/NEWS
@@ -66,6 +66,10 @@ Version 2.26
 * The port to Native Client running on ARMv7-A (--host=arm-nacl) has been
   removed.
 
+* The reallocarray function has been added to libc.  It is a realloc
+  replacement with a check for integer overflow when calculating total
+  allocation size.
+
 Security related changes:
 
 * The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes,
diff --git a/include/stdlib.h b/include/stdlib.h
index c3ee680bd6..5847445fd3 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -110,6 +110,10 @@ extern int __posix_memalign (void **memptr, size_t alignment, size_t size);
 extern void *__libc_memalign (size_t alignment, size_t size)
      __attribute_malloc__;
 
+extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+libc_hidden_proto (__libc_reallocarray)
+
 extern int __libc_system (const char *line);
 
 
diff --git a/malloc/Makefile b/malloc/Makefile
index d0f23f7bf3..b7d4c63920 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -26,7 +26,7 @@ dist-headers := malloc.h
 headers := $(dist-headers) obstack.h mcheck.h
 tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
 	 tst-mcheck tst-mallocfork tst-trim1 \
-	 tst-malloc-usable tst-realloc tst-posix_memalign \
+	 tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
 	 tst-pvalloc tst-memalign tst-mallopt \
 	 tst-malloc-backtrace tst-malloc-thread-exit \
 	 tst-malloc-thread-fail tst-malloc-fork-deadlock \
@@ -49,7 +49,7 @@ endif
 tests += $(tests-static)
 test-srcs = tst-mtrace
 
-routines = malloc morecore mcheck mtrace obstack \
+routines = malloc morecore mcheck mtrace obstack reallocarray \
   scratch_buffer_grow scratch_buffer_grow_preserve \
   scratch_buffer_set_array_size
 
diff --git a/malloc/Versions b/malloc/Versions
index e34ab177be..23aafb5ccc 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -62,6 +62,7 @@ libc {
     aligned_alloc;
   }
   GLIBC_2.26 {
+    reallocarray;
   }
   GLIBC_PRIVATE {
     # Internal startup hook for libpthread.
@@ -74,5 +75,8 @@ libc {
     __libc_scratch_buffer_grow;
     __libc_scratch_buffer_grow_preserve;
     __libc_scratch_buffer_set_array_size;
+
+    # Internal name for reallocarray
+    __libc_reallocarray;
   }
 }
diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index de6103d7e1..dbd801a58e 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -81,5 +81,24 @@ void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
 /* Called in the child process after a fork.  */
 void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
 
+/* Set *RESULT to LEFT * RIGHT.  Return true if the multiplication
+   overflowed.  */
+static inline bool
+check_mul_overflow_size_t (size_t left, size_t right, size_t *result)
+{
+#if __GNUC__ >= 5
+  return __builtin_mul_overflow (left, right, result);
+#else
+  /* size_t is unsigned so the behavior on overflow is defined.  */
+  *result = left * right;
+  size_t half_size_t = ((size_t) 1) << (8 * sizeof (size_t) / 2);
+  if (__glibc_unlikely ((left | right) >= half_size_t))
+    {
+      if (__glibc_unlikely (right != 0 && *result / right != left))
+        return true;
+    }
+  return false;
+#endif
+}
 
 #endif /* _MALLOC_INTERNAL_H */
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 274c0958e4..339ab64c7d 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -49,6 +49,14 @@ __THROW __attribute_malloc__ __wur;
 extern void *realloc (void *__ptr, size_t __size)
 __THROW __attribute_warn_unused_result__;
 
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+__THROW __attribute_warn_unused_result__;
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/malloc/reallocarray.c b/malloc/reallocarray.c
new file mode 100644
index 0000000000..07562c30c9
--- /dev/null
+++ b/malloc/reallocarray.c
@@ -0,0 +1,37 @@
+/* Change the size of an allocated block.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <malloc/malloc-internal.h>
+
+void *
+__libc_reallocarray (void *optr, size_t nmemb, size_t elem_size)
+{
+  size_t bytes;
+  if (check_mul_overflow_size_t (nmemb, elem_size, &bytes))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+  else
+    return realloc (optr, bytes);
+}
+libc_hidden_def (__libc_reallocarray)
+
+weak_alias (__libc_reallocarray, reallocarray)
diff --git a/malloc/tst-reallocarray.c b/malloc/tst-reallocarray.c
new file mode 100644
index 0000000000..f1cbf7fe0a
--- /dev/null
+++ b/malloc/tst-reallocarray.c
@@ -0,0 +1,118 @@
+/* Test for reallocarray.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  void *ptr = NULL;
+  void *ptr2 = NULL;
+  unsigned char *c;
+  size_t i;
+  int ok;
+  const size_t max = ~(size_t)0;
+  size_t a, b;
+
+  /* Test overflow detection.  */
+  errno = 0;
+  ptr = reallocarray (NULL, max, 2);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, 2, max);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  a = 65537;
+  b = max/65537 + 1;
+  errno = 0;
+  ptr = reallocarray (NULL, a, b);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  errno = 0;
+  ptr = reallocarray (NULL, b, a);
+  TEST_VERIFY (!ptr);
+  TEST_VERIFY (errno == ENOMEM);
+
+  /* Test realloc-like behavior.  */
+  /* Allocate memory like malloc.  */
+  ptr = reallocarray (NULL, 10, 2);
+  TEST_VERIFY_EXIT (ptr);
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 10*2);
+
+  memset (ptr, 0xAF, 10*2);
+
+  /* Enlarge buffer.   */
+  ptr2 = reallocarray (ptr, 20, 2);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY (malloc_usable_size (ptr) >= 20*2);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 10*2; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Decrease buffer size.  */
+  ptr2 = reallocarray (ptr, 5, 3);
+  TEST_VERIFY (ptr2);
+  if (ptr2)
+    ptr = ptr2;
+  TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 5*3);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  /* Overflow should leave buffer untouched.  */
+  errno = 0;
+  ptr2 = reallocarray (ptr, 2, ~(size_t)0);
+  TEST_VERIFY (!ptr2);
+  TEST_VERIFY (errno == ENOMEM);
+
+  c = ptr;
+  ok = 1;
+  for (i = 0; i < 5*3; ++i)
+    {
+      if (c[i] != 0xAF)
+        ok = 0;
+    }
+  TEST_VERIFY (ok);
+
+  free (ptr);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/manual/memory.texi b/manual/memory.texi
index a256ca07b2..fb6b594ef1 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -751,8 +751,8 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
 @comment malloc.h stdlib.h
@@ -816,9 +816,29 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
-Like @code{malloc}, @code{realloc} may return a null pointer if no
-memory space is available to make the block bigger.  When this happens,
-the original block is untouched; it has not been modified or relocated.
+@comment malloc.h stdlib.h
+@comment BSD
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails safely if
+the multiplication overflows, by setting @code{errno} to @code{ENOMEM},
+returning a null pointer, and leaving the original block unchanged.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+
+@strong{Portability Note:} This function is not part of any standard.  It was
+first introduced in OpenBSD 5.6.
+@end deftypefun
+
+Like @code{malloc}, @code{realloc} and @code{reallocarray} may return a null
+pointer if no memory space is available to make the block bigger.  When this
+happens, the original block is untouched; it has not been modified or
+relocated.
 
 In most cases it makes no difference what happens to the original block
 when @code{realloc} fails, because the application program cannot continue
@@ -838,16 +858,17 @@ xrealloc (void *ptr, size_t size)
 @}
 @end smallexample
 
-You can also use @code{realloc} to make a block smaller.  The reason you
-would do this is to avoid tying up a lot of memory space when only a little
-is needed.
+You can also use @code{realloc} or @code{reallocarray} to make a block
+smaller.  The reason you would do this is to avoid tying up a lot of memory
+space when only a little is needed.
 @comment The following is no longer true with the new malloc.
 @comment But it seems wise to keep the warning for other implementations.
 In several allocation implementations, making a block smaller sometimes
 necessitates copying it, so it can fail if no other space is available.
 
-If the new size you specify is the same as the old size, @code{realloc}
-is guaranteed to change nothing and return the same address that you gave.
+If the new size you specify is the same as the old size, @code{realloc} and
+@code{reallocarray} are guaranteed to change nothing and return the same
+address that you gave.
 
 @node Allocating Cleared Space
 @subsubsection Allocating Cleared Space
@@ -1588,6 +1609,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 99125f2d23..428ca2ef68 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -422,6 +422,17 @@ extern void *calloc (size_t __nmemb, size_t __size)
    between objects pointed by the old and new pointers.  */
 extern void *realloc (void *__ptr, size_t __size)
      __THROW __attribute_warn_unused_result__;
+
+#ifdef __USE_GNU
+/* Re-allocate the previously allocated block in PTR, making the new
+   block large enough for NMEMB elements of SIZE bytes each.  */
+/* __attribute_malloc__ is not used, because if reallocarray returns
+   the same pointer that was passed to it, aliasing needs to be allowed
+   between objects pointed by the old and new pointers.  */
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+     __THROW __attribute_warn_unused_result__;
+#endif
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
 extern void free (void *__ptr) __THROW;
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 58d768c6bc..a494c3947d 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 906050d2c3..2fc1a9bae7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 66112dd0a7..4465a62ff1 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -98,6 +98,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3ddadd2a24..96126d9e6a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1862,6 +1862,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 977ab90bc7..aae351bbff 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2020,6 +2020,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index c7edb9a272..81ec65bec0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 450be4e9c1..9db205b68e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 9e016bd76e..ee59e950b6 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1976,6 +1976,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 1a455be0f5..feb869757c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2097,3 +2097,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8eb5e668b9..a5b1c42929 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1951,6 +1951,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 416d9ac0ae..570a859aac 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1949,6 +1949,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index f4949e5a38..71008ad873 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1947,6 +1947,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index c7375aee3f..1a07d66caf 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 724a0e3a04..a62a41be62 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2138,3 +2138,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 2dc32b631c..f4f11dc625 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 5658109ca2..2977569f2c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1985,6 +1985,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c761221ffe..271d32e19b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2185,3 +2185,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 265c76914b..372ef67c27 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -99,6 +99,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index ed1b6bf26f..705ff851a9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1980,6 +1980,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 2e75d29e47..21fd2b5671 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1881,6 +1881,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index bd74c0cdab..313a71e589 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5584838409..94a4fb2213 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1972,6 +1972,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index efedbe2874..6db5811c3f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1910,6 +1910,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index f0c13ceea8..ce14ceb15f 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffd988a33d..5d83926aac 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index f57004c860..f69de7aa83 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1861,6 +1861,8 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 05629e17e7..a330855308 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2104,3 +2104,5 @@ GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 reallocarray F
-- 
2.12.2

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7] Add reallocarray function.
  2017-05-30 20:50                                 ` [PATCH v7] " Dennis Wölfing
@ 2017-05-30 22:06                                   ` Adhemerval Zanella
  0 siblings, 0 replies; 48+ messages in thread
From: Adhemerval Zanella @ 2017-05-30 22:06 UTC (permalink / raw)
  To: Dennis Wölfing, libc-alpha



On 30/05/2017 17:50, Dennis Wölfing wrote:
> The reallocarray function is an extension from OpenBSD.  It is an
> integer-overflow-safe replacement for realloc(p, X*Y) and
> malloc(X*Y) (realloc(NULL, X*Y)).  It can therefore help in preventing
> certain security issues in code.
> 
> This is an updated version of a patch originally submitted by Rüdiger
> Sonderfeld in May 2014.
> See <https://sourceware.org/ml/libc-alpha/2014-05/msg00481.html>.
> 
> Tested on i686 and x86_64.

Pushed upstream as 2e0bbbfbf95fc9e22692e93658a6fbdd2d4554da.

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2017-05-30 22:06 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-10 15:01 [PATCH] Add reallocarray function Dennis Wölfing
2017-04-10 15:18 ` Zack Weinberg
2017-04-10 18:27   ` Dennis Wölfing
2017-04-16 13:19     ` Dennis Wölfing
2017-04-16 13:38       ` Florian Weimer
2017-04-10 16:03 ` Andreas Schwab
2017-04-11  7:55 ` Florian Weimer
2017-04-12 15:24   ` Dennis Wölfing
2017-04-12 16:35     ` Florian Weimer
2017-04-17 14:02 ` [PATCH v2] " Dennis Wölfing
2017-04-17 14:32   ` Florian Weimer
2017-04-17 14:34     ` Paul Eggert
2017-04-17 14:40     ` Dennis Wölfing
2017-04-17 14:44       ` Florian Weimer
2017-04-18 12:34   ` Carlos O'Donell
2017-04-18 14:29     ` Dennis Wölfing
2017-04-18 15:50       ` Carlos O'Donell
2017-04-18 15:57         ` Dennis Wölfing
2017-04-19 15:16           ` Joseph Myers
2017-04-19 15:02   ` Joseph Myers
2017-04-21 12:16   ` [PATCH v3] " Dennis Wölfing
2017-04-28  8:57     ` Dennis Wölfing
2017-05-08  7:07       ` Dennis Wölfing
2017-05-08  7:34     ` Florian Weimer
2017-05-10 13:03       ` [PATCH v4] " Dennis Wölfing
2017-05-10 21:29         ` DJ Delorie
2017-05-11 17:00           ` Dennis Wölfing
2017-05-11 17:28             ` DJ Delorie
2017-05-11 18:36               ` Dennis Wölfing
2017-05-11 18:41                 ` DJ Delorie
2017-05-15 12:22         ` [PATCH v5] " Dennis Wölfing
2017-05-22 14:16           ` Dennis Wölfing
2017-05-22 18:24             ` DJ Delorie
2017-05-22 18:51               ` Zack Weinberg
2017-05-22 20:25                 ` [PATCH v6] " Dennis Wölfing
2017-05-29 12:29                   ` Dennis Wölfing
2017-05-30 16:02                     ` DJ Delorie
2017-05-30 16:17                       ` Zack Weinberg
2017-05-30 20:02                         ` Dennis Wölfing
2017-05-30 20:35                           ` Adhemerval Zanella
2017-05-30 20:38                             ` Dennis Wölfing
2017-05-30 20:40                               ` Adhemerval Zanella
2017-05-30 20:50                                 ` [PATCH v7] " Dennis Wölfing
2017-05-30 22:06                                   ` Adhemerval Zanella
2017-05-30 15:17                   ` [PATCH v6] " Adhemerval Zanella
2017-05-30 20:02                     ` Dennis Wölfing
2017-05-30 20:16                       ` Florian Weimer
2017-05-30 20:27                       ` Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).