]> Savannah Git Hosting - gnulib.git/commitdiff
realloc-posix: realloc (p, 0) yields nonnull
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 30 Oct 2024 05:01:42 +0000 (22:01 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 30 Oct 2024 05:02:09 +0000 (22:02 -0700)
* lib/realloc.c: Include <stdckdint.h>, not "xalloc-oversized.h".
Use of xalloc_oversized replaced by ckd_add.
(rpl_realloc) [!NEED_SANITIZED_REALLOC]:
Treat realloc (p, 0) as if it were a realloc (p, 1) that never fails.
That’s easier, reduces module dependencies,
and better supports the future alloc-0-nonnull module.
* modules/realloc-posix (Depends-on): Remove free-posix,
malloc-posix, xalloc-oversized.  Add stdckdint.

ChangeLog
lib/realloc.c
modules/realloc-posix

index 73b74b9641a0cd0352c67874770977acce90939c..eb0e39c9fd0888efd83ded8796934f8c48fc923b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2024-10-29  Paul Eggert  <eggert@cs.ucla.edu>
+
+       realloc-posix: realloc (p, 0) yields nonnull
+       * lib/realloc.c: Include <stdckdint.h>, not "xalloc-oversized.h".
+       Use of xalloc_oversized replaced by ckd_add.
+       (rpl_realloc) [!NEED_SANITIZED_REALLOC]:
+       Treat realloc (p, 0) as if it were a realloc (p, 1) that never fails.
+       That’s easier, reduces module dependencies,
+       and better supports the future alloc-0-nonnull module.
+       * modules/realloc-posix (Depends-on): Remove free-posix,
+       malloc-posix, xalloc-oversized.  Add stdckdint.
+
 2024-10-29  Collin Funk  <collin.funk1@gmail.com>
 
        backupfile: Remove non-existent module dependency.
index 5cfe3bc7472da68a0ab5732102ad271116e590ef..b8570f39291d3f1c5252319354f16353d4c75b57 100644 (file)
@@ -23,8 +23,7 @@
 #include <stdlib.h>
 
 #include <errno.h>
-
-#include "xalloc-oversized.h"
+#include <stdckdint.h>
 
 /* Call the system's realloc below.  This file does not define
    _GL_USE_STDLIB_ALLOC because it needs Gnulib's malloc if present.  */
 void *
 rpl_realloc (void *p, size_t n)
 {
-  if (p == NULL)
-    return malloc (n);
-
   if (n == 0)
     {
 #if NEED_SANITIZED_REALLOC
-      /* ISO C 23 § 7.24.3.7.(3) says that this case is undefined behaviour.
-         Let the programmer know that it occurred.
+      /* When P is non-null, ISO C23 §7.24.3.7.(3) says realloc (P, 0) has
+         undefined behavior even though C17 and earlier partially defined
+         the behavior.  Let the programmer know.
          When the undefined-behaviour sanitizers report this case, i.e. when
          <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117233> and
          <https://github.com/llvm/llvm-project/issues/113065>
          have been closed and new releases of GCC and clang have been made,
-         we can remove this code here.  */
-      abort ();
-#else
-      free (p);
-      return NULL;
+         we can revisit this code.  */
+      if (p != NULL)
+        abort ();
 #endif
+
+      /* When P is null, act like glibc malloc, i.e., like malloc (1)
+         except the caller cannot dereference any non-null return.
+
+         When P is non-null, POSIX.1-2024 extends C17 to say that
+         realloc (P, 0) either fails and returns a null pointer,
+         or succeeds by freeing P and then either:
+           (a) setting errno=EINVAL and returning a null pointer; or
+           (b) acting like a successful malloc (0).
+         GNU realloc acts like (a) except it does not set errno;
+         this conforms to C17 and to C23 but not to POSIX.1-2024.
+         Quite possibly future versions of POSIX will change,
+         due either to C23 or to (a)'s semantics being messy.
+         Act like (b), as that's easy, matches GNU, BSD and V7 malloc,
+         matches BSD and V7 realloc, and is convenient for Gnulib.
+         Do not fail if P is nonnull, though, as it's natural for callers
+         to assume that realloc (P, 0) can fail only when P is null.  */
+
+      void *result = realloc (p, 1);
+      return result ? result : p;
     }
 
-  if (xalloc_oversized (n, 1))
+  ptrdiff_t signed_n;
+  if (ckd_add (&signed_n, n, 0))
     {
       errno = ENOMEM;
       return NULL;
index c87d7edd476a56846a23e94c348a51d9b0c67c74..566d38919408a559ddbba4540a430fffb3d8a75d 100644 (file)
@@ -7,10 +7,8 @@ m4/realloc.m4
 m4/malloc.m4
 
 Depends-on:
+stdckdint            [test $REPLACE_REALLOC_FOR_REALLOC_POSIX = 1]
 stdlib
-free-posix           [test $REPLACE_REALLOC_FOR_REALLOC_POSIX = 1]
-malloc-posix         [test $REPLACE_REALLOC_FOR_REALLOC_POSIX = 1]
-xalloc-oversized     [test $REPLACE_REALLOC_FOR_REALLOC_POSIX = 1]
 
 configure.ac:
 gl_FUNC_REALLOC_POSIX