]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
reallocarray: check for ptrdiff_t overflow
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 24 Apr 2021 17:45:45 +0000 (10:45 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 24 Apr 2021 17:47:40 +0000 (10:47 -0700)
* doc/glibc-functions/reallocarray.texi (reallocarray):
Mention ptrdiff_t overflow.
* lib/reallocarray.c (reallocarray): Reindent as per usual GNU.
* lib/stdlib.in.h (reallocarray): Allow reallocarray to be replaced.
* m4/reallocarray.m4 (gl_FUNC_REALLOCARRAY):
Check for ptrdiff_t overflow.
* m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Set up REPLACE_REALLOCARRAY.
* modules/reallocarray (Files): Add malloc.m4.
(configure.ac): Also test REPLACE_REALLOCARRAY.
* modules/reallocarray-tests (Depends-on): Add stdint.
* modules/stdlib (stdlib.h): Substitute REPLACE_REALLOCARRAY.
* tests/test-reallocarray.c: Include stdint.h.
(main): Check for ptrdiff_t overflow.

ChangeLog
doc/glibc-functions/reallocarray.texi
lib/reallocarray.c
lib/stdlib.in.h
m4/reallocarray.m4
m4/stdlib_h.m4
modules/reallocarray
modules/reallocarray-tests
modules/stdlib
tests/test-reallocarray.c

index baa74c3c62ba20f746f0f4bbe7dda64f0d7e9560..c198830bf5c088a9ec7ee5fae38939778d781e84 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 2021-04-24  Paul Eggert  <eggert@cs.ucla.edu>
 
+       reallocarray: check for ptrdiff_t overflow
+       * doc/glibc-functions/reallocarray.texi (reallocarray):
+       Mention ptrdiff_t overflow.
+       * lib/reallocarray.c (reallocarray): Reindent as per usual GNU.
+       * lib/stdlib.in.h (reallocarray): Allow reallocarray to be replaced.
+       * m4/reallocarray.m4 (gl_FUNC_REALLOCARRAY):
+       Check for ptrdiff_t overflow.
+       * m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Set up REPLACE_REALLOCARRAY.
+       * modules/reallocarray (Files): Add malloc.m4.
+       (configure.ac): Also test REPLACE_REALLOCARRAY.
+       * modules/reallocarray-tests (Depends-on): Add stdint.
+       * modules/stdlib (stdlib.h): Substitute REPLACE_REALLOCARRAY.
+       * tests/test-reallocarray.c: Include stdint.h.
+       (main): Check for ptrdiff_t overflow.
+
        calloc-gnu-tests: add overflow tests
        * tests/test-calloc-gnu.c (identity): New function, replacing ‘eight’.
        (main): Do 2 * log2(SIZE_MAX) tests instead of just two tests.
index 903233df198e6b0a86816986390c0ce8ef277e40..b1337eff21d9bd298a05df642adeed07268511b7 100644 (file)
@@ -26,6 +26,12 @@ Portability problems fixed by Gnulib:
 @item
 This function is missing on many platforms:
 glibc 2.25, macOS 11.1, FreeBSD 10, NetBSD 7, OpenBSD 5.5, Minix 3.3.0, AIX 7.2, HP-UX 11, IRIX, Solaris 11.4, Cygwin 1.7.x, mingw, MSVC 14, Android 9.0.
+
+@item
+On some platforms, @code{reallocarray (n, s)} can succeed even if
+multiplying @code{n} by @code{s} would exceed @code{PTRDIFF_MAX},
+which can lead to undefined behavior later:
+FreeBSD 13, NetBSD 9, OpenBSD 6, musl 1.2.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index d10d7d5f57ad67724e6714c9f8cdb8b400eee534..03197c601b484edae3bfde578017edeab7979e93 100644 (file)
 void *
 reallocarray (void *ptr, size_t nmemb, size_t size)
 {
-    if (xalloc_oversized (nmemb, size))
-      {
-        errno = ENOMEM;
-        return NULL;
-      }
-
-    /* Rely on the semantics of GNU realloc.  */
-    return realloc (ptr, nmemb * size);
+  if (xalloc_oversized (nmemb, size))
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+
+  /* Rely on the semantics of GNU realloc.  */
+  return realloc (ptr, nmemb * size);
 }
index c07fd1f5d7bb99760e6f664cc0a794cc3ca11a12..91079b1cf109c2abfbed12bf940c38b915a9bfbd 100644 (file)
@@ -1032,12 +1032,23 @@ _GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - "
 
 
 #if @GNULIB_REALLOCARRAY@
-# if ! @HAVE_REALLOCARRAY@
+# if @REPLACE_REALLOCARRAY@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef reallocarray
+#   define reallocarray rpl_reallocarray
+#  endif
+_GL_FUNCDECL_RPL (reallocarray, void *,
+                  (void *ptr, size_t nmemb, size_t size));
+_GL_CXXALIAS_RPL (reallocarray, void *,
+                  (void *ptr, size_t nmemb, size_t size));
+# else
+#  if ! @HAVE_REALLOCARRAY@
 _GL_FUNCDECL_SYS (reallocarray, void *,
                   (void *ptr, size_t nmemb, size_t size));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (reallocarray, void *,
                   (void *ptr, size_t nmemb, size_t size));
+# endif
 _GL_CXXALIASWARN (reallocarray);
 #elif defined GNULIB_POSIXCHECK
 # undef reallocarray
index 1d81451862876d7a3a64172816e9feeae15734e4..9d8a626622e977770440f0153e8ee3ad167aa75d 100644 (file)
@@ -1,4 +1,4 @@
-# reallocarray.m4 serial 2
+# reallocarray.m4 serial 3
 dnl Copyright (C) 2017-2021 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -10,9 +10,12 @@ AC_DEFUN([gl_FUNC_REALLOCARRAY],
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+  AC_REQUIRE([gl_CHECK_MALLOC_PTRDIFF])
   AC_CHECK_FUNCS([reallocarray])
   if test "$ac_cv_func_reallocarray" = no; then
     HAVE_REALLOCARRAY=0
+  elif test "$gl_cv_malloc_ptrdiff" = no; then
+    REPLACE_REALLOCARRAY=1
   fi
 ])
 
index 2de57f78c43b3f21cfbb89d3579e0f924e772801..9c1d1c76c13c5e58524c4acb1edcc2460005096b 100644 (file)
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 62
+# stdlib_h.m4 serial 63
 dnl Copyright (C) 2007-2021 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -179,6 +179,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   REPLACE_RANDOM=0;          AC_SUBST([REPLACE_RANDOM])
   REPLACE_RANDOM_R=0;        AC_SUBST([REPLACE_RANDOM_R])
   REPLACE_REALLOC=0;         AC_SUBST([REPLACE_REALLOC])
+  REPLACE_REALLOCARRAY=0;    AC_SUBST([REPLACE_REALLOCARRAY])
   REPLACE_REALPATH=0;        AC_SUBST([REPLACE_REALPATH])
   REPLACE_SETENV=0;          AC_SUBST([REPLACE_SETENV])
   REPLACE_SETSTATE=0;        AC_SUBST([REPLACE_SETSTATE])
index a64c6fd2d0d015eb5e190e7e66f8e6d49ebcd34a..6d762c157a8480a34e0184c5eff38446e11fac0d 100644 (file)
@@ -3,6 +3,7 @@ reallocarray function that is glibc compatible.
 
 Files:
 lib/reallocarray.c
+m4/malloc.m4
 m4/reallocarray.m4
 
 Depends-on:
@@ -13,7 +14,7 @@ stdlib
 
 configure.ac:
 gl_FUNC_REALLOCARRAY
-if test $HAVE_REALLOCARRAY = 0; then
+if test $HAVE_REALLOCARRAY = 0 || test $REPLACE_REALLOCARRAY = 1; then
   AC_LIBOBJ([reallocarray])
   gl_PREREQ_REALLOCARRAY
 fi
index 3943d7295bfd386a235bac904f3f8b3f1caa7834..4b61da14351c0d093c38314204c67e43fe69dfb2 100644 (file)
@@ -3,6 +3,7 @@ tests/test-reallocarray.c
 tests/signature.h
 
 Depends-on:
+stdint
 
 configure.ac:
 
index 47f3af752a7505b658ac510a12353b914ff4c06e..da5629dc9aba9445fc5d0c25326db0b088cc26d4 100644 (file)
@@ -137,6 +137,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
              -e 's|@''REPLACE_RANDOM''@|$(REPLACE_RANDOM)|g' \
              -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \
              -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \
+             -e 's|@''REPLACE_REALLOCARRAY''@|$(REPLACE_REALLOCARRAY)|g' \
              -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \
              -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
              -e 's|@''REPLACE_SETSTATE''@|$(REPLACE_SETSTATE)|g' \
index 9c4a189efc24e4dfe75cc1fdf27dccaea9cb2a23..973f22ba66d42e0fa603db4dc3013b63a5f22b91 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <stdlib.h>
 #include <errno.h>
+#include <stdint.h>
 
 #include "signature.h"
 SIGNATURE_CHECK (reallocarray, void *, (void *, size_t, size_t));
@@ -25,20 +26,24 @@ SIGNATURE_CHECK (reallocarray, void *, (void *, size_t, size_t));
 int
 main ()
 {
-   size_t n;
-
-   /* Check that reallocarray fails when requested to allocate a block
-      of memory larger than SIZE_MAX bytes.  */
-   for (n = 2; n != 0; n <<= 1)
-     {
-       void *volatile p = reallocarray (NULL, (size_t) -1 / n + 1, n);
-       if (p)
-         return 1;
-
-       /* Ensure that errno is correctly set.  */
-       if (errno != ENOMEM)
-         return 1;
-     }
-
-   return 0;
+  void *volatile p = NULL;
+
+  /* Check that reallocarray fails when requested to allocate a block
+     of memory larger than PTRDIFF_MAX or SIZE_MAX bytes.  */
+  for (size_t n = 2; n != 0; n <<= 1)
+    {
+      p = reallocarray (p, PTRDIFF_MAX / n + 1, n);
+      if (p)
+        return 1;
+      if (errno != ENOMEM)
+        return 2;
+
+      p = reallocarray (p, SIZE_MAX / n + 1, n);
+      if (p)
+        return 3;
+      if (errno != ENOMEM)
+        return 4;
+    }
+
+  return 0;
 }