BUG: realloc(p,0) should be consistent with malloc(0)

Wilco Dijkstra Wilco.Dijkstra@arm.com
Wed Jun 18 22:11:01 GMT 2025


Hi Alejandro,

> > And those are the 4 words that allow one to call free(p) AND return NULL.
>
> By 'one' you mean realloc(p,0), I guess.
>
> No.  Anything that starts by "If size is non-zero" does NOT give any
> allowance for what can happen if size is zero.

Of course it does. It HAS to explicitly exclude zero here to allow that case,
otherwise the zero case must do the same as for any other size, and then
there would be no point in specifying all the errno crazyness.

Look at what it claims:

"The ISO C standard makes it implementation-defined whether a call to realloc(p, 0)
frees the space pointed to by p if it returns a null pointer because memory for the
new object was not allocated. POSIX.1 instead requires that implementations set
errno if a null pointer is returned and the space has not been freed, and POSIX
applications should only free the space if errno was changed."

So if realloc (p, 0) returns NULL AND sets errno then it must not free the block.
However if it doesn't set errno, then it must free the block.

Basically POSIX requires you to write something like this for every realloc:

errno = 0;
newp = realloc (oldp, size);
if (newp == NULL)
{
  if (size == 0 && errno == EINVAL)
    free (oldp);           // only free old block if errno set
  else if (size == 0)
    // do NOT free oldp (OK for current GLIBC, memory leak for other allocators)
  else if (size != 0)
    free (oldp);           // oldp valid, so free it
}
else
{
   free (newp);
}

> And BTW, if it has to set errno to EINVAL, it means it should not free
> the input pointer, so it clearly is non-conforming.

Setting EINVAL and freeing it would be non-conforming. But that's not what
GLIBC does!

POSIX can be fixed by removing the "size is non-zero" part and the useless
errno handling. Then the code above just becomes:

newp = realloc (oldp, size);
if (newp == NULL)
{
  free (oldp);           // oldp was not freed (this will crash GLIBC if size == 0)
}
else
{
  free (newp);
}

> Which versions of each standard are you reading?  ISO C23 makes r(p,0)
> UB, so there's nothing similar to POSIX in ISO C.

https://pubs.opengroup.org/onlinepubs/9799919799/functions/realloc.html
The quote above says ISO C, I'm assuming it means the latest version.

Cheers,
Wilco


More information about the Libc-alpha mailing list