glibc's realloc(3) is broken. It was originally good (I believe) until
at some point, when it was changed to conform to C89, which had a bogus
specification that required that it returns NULL. C99 fixed the mistake
from C89, and so glibc's realloc(3) is non-conforming to
C99/C11/POSIX.1-2008. C17 broke again the definition of realloc(3).
Link: <https://github.com/shadow-maint/shadow/pull/1095>
Link: <https://nabijaczleweli.xyz/content/blogn_t/017-malloc0.html>
Link: <https://inbox.sourceware.org/libc-alpha/5gclfbrxfd7446gtwd2x2gfuquy7ukjdbrndphyfmfszxlft76@wwjz7spd4vd7/T/#t>
Co-developed-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Acked-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
#define REALLOC(p, n, type) \
( \
- _Generic(p, type *: (type *) reallocarray(p, n, sizeof(type))) \
+ _Generic(p, type *: (type *) reallocarray(p, (n) ?: 1, sizeof(type))) \
)
#define REALLOCF(p, n, type) \
( \
- _Generic(p, type *: (type *) reallocarrayf(p, n, sizeof(type))) \
+ _Generic(p, type *: (type *) reallocarrayf(p, (n) ?: 1, sizeof(type)))\
)
{
void *q;
- q = reallocarray(p, nmemb, size);
+ q = reallocarray(p, nmemb ?: 1, size ?: 1);
- /* realloc(p, 0) is equivalent to free(p); avoid double free. */
- if (q == NULL && nmemb != 0 && size != 0)
+ if (q == NULL)
free(p);
return q;
}