From: Paul Eggert Date: Sat, 19 Oct 2024 21:18:49 +0000 (-0700) Subject: realloc: more improvements for realloc (p, 0) X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=6af4a4ef0d1be2f133937ae1f6686770787bb47d;p=gnulib.git realloc: more improvements for realloc (p, 0) * doc/posix-functions/realloc.texi (realloc): Document more realloc (p, 0) gotchas: evolution of C standards, errno values, which glibc versions do what, how programs might misbehave, what happens when not growing. --- diff --git a/ChangeLog b/ChangeLog index 1c58b474c3..0b7094e650 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2024-10-19 Paul Eggert + + realloc: more improvements for realloc (p, 0) + * doc/posix-functions/realloc.texi (realloc): + Document more realloc (p, 0) gotchas: evolution of C standards, + errno values, which glibc versions do what, how programs might + misbehave, what happens when not growing. + 2024-10-19 Bruno Haible realloc: Improve documentation. diff --git a/doc/posix-functions/realloc.texi b/doc/posix-functions/realloc.texi index 9eec174fa1..fe35a9fb80 100644 --- a/doc/posix-functions/realloc.texi +++ b/doc/posix-functions/realloc.texi @@ -7,6 +7,7 @@ POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9799919799/fun Gnulib module: realloc-posix Portability problems fixed by Gnulib: + @itemize @item Upon failure, the function does not set @code{errno} to @code{ENOMEM} on @@ -22,37 +23,67 @@ so @code{realloc-posix} does not allow going over the limit. Without the @samp{realloc-gnu} module described below, it is not portable to call @code{realloc} with a size of 0. With a -NULL pointer argument, this is the same ambiguity as @code{malloc (0)} -on whether a unique zero-size object is created. With a non-NULL -pointer argument @code{p}, C17 says that it is implementation-defined -whether @code{realloc (p, 0)} frees @code{p}. -Behavior varies among systems: @code{realloc (p, 0)} -@itemize +null pointer argument, this is the same ambiguity as @code{malloc (0)} +on whether a unique zero-size memory region is created. + +Behavior is a real mess for @code{realloc (p, 0)} with non-null @code{p}. +C23 says behavior is undefined. +C17 says it is implementation-defined whether @code{realloc} +returns a null pointer or a pointer to a new zero-sized memory region. +C89 through C11 say @code{realloc} returns a null pointer. +No standard says whether @code{errno} is preserved when +@code{realloc} successfully returns a null pointer. +In practice, platforms have one of the following behaviors: + +@enumerate @item -always frees @code{p} and successfully returns a null pointer -(on glibc, AIX, native Windows, Android). +Always free @code{p}, without changing @code{errno} and return a null pointer: +(glibc 2.1.1--2.40, most likely glibc 2.41+ at least by default, Android). + @item -usually succeeds and -returns a pointer to freshly-allocated memory of 1 byte -(on musl libc, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, Cygwin). +Always free @code{p}, possibly set @code{errno}, and return a null pointer: +(AIX, mingw, MSVC). + @item -always fails and leaves @code{p} valid (no known system does this), or +Always free @code{p} without changing @code{errno} +and then return a pointer to a new region of size zero: +(glibc 1--2.1, perhaps glibc 2.41+ in some configurations). + @item -usually succeeds and returns a unique zero-size object -(no known system does this). -@end itemize -A program not suspecting these variations in semantics will +When successful free @code{p}, possibly set @code{errno}, +and then return a pointer to a new region of size zero; +when unsuccessful do not free @code{p}, set @code{errno}, +and return a null pointer: +(musl libc, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, Cygwin). +@end enumerate + +@noindent +A program not suspecting these variations in semantics will either: + @itemize @item -either leak memory (the still-valid @code{p}), -if it assumes the first behaviour but the system implements the second one, +Leak memory (the still-valid @code{p}), +if it assumes behavior (1) or (2) but the system implements (3) or (4). + +@item +Falsely respond to memory exhaustion (if it checks for realloc failure, +as it should) or have double-free bugs (if it does not check), +if it assumes behavior (3) or (4) but the system implements (1) or (2). +@end itemize + +Portability problems not fixed by Gnulib: + +@itemize @item -have double-free bugs, -if it assumes the second behaviour but the system implements the first one. +When not growing an already-allocated region, i.e., +when @code{p} points to a region of size @code{psize} and @code{n <= psize}, +the standards allow @code{realloc (p, n)} to fail and return a null pointer. +It is not known which, if any, implementations actually fail in this situation. @end itemize Extension: Gnulib provides a module @samp{realloc-gnu} that substitutes a -@code{realloc} implementation that behaves more like the glibc implementation. +@code{realloc} implementation that behaves more like the current +glibc implementation. It fixes these portability problems: @itemize