Hi Rich, On Thu, Jun 19, 2025 at 11:32:09AM -0400, Rich Felker wrote: > On Thu, Jun 19, 2025 at 03:57:47PM +0200, Alejandro Colomar wrote: > > Hi, > > > > Here's a revision of this change, addressing some concerns. I'm only > > showing the formatted changes, since the patch itself is unimportant. > > > > > > Have a lovely day! > > Alex > > > > --- > > $ MANWIDTH=72 diffman-git HEAD > > --- HEAD^:man/man3/malloc.3 > > +++ HEAD:man/man3/malloc.3 > > @@ -126,15 +126,32 @@ > > │ realloc() │ │ │ > > └────────────────────────────────────┴───────────────┴─────────┘ > > > > +VERSIONS > > + The behavior of realloc(p, 0) in glibc doesn’t conform to any of > > + C99, C11, POSIX.1‐2001, POSIX.1‐2008, POSIX.1‐2017, or > > + POSIX.1‐2024. The C17 specification was changed to make it con‐ > > + forming, but that specification was broken —it is impossible to > > + write code that works portably—, and C23 changed it again to > > + make this undefined behavior, acknowledging that the C17 speci‐ > > + fication was broad enough that undefined behavior wasn’t worse > > + than that. > > This is still full of your polemics. The word "broken" generally > belongs in personal blog posts, not a manual that's supposed to be > documenting the facts of an interface.
Hmmm, agree. I've changed the wording:
@@ -252,8 +265,10 @@ .SH VERSIONS
POSIX.1-2017,
or POSIX.1-2024.
The C17 specification was changed to make it conforming,
-but that specification was broken
-\[em]it is impossible to write code that works portably\[em],
+but that specification made it
+impossible to write code that
+reliably determines if the input pointer is freed after
+.IR realloc(p,\~0) ,
and C23 changed it again to make this undefined behavior,
acknowledging that the C17 specification was broad enough that
undefined behavior wasn't worse than that.
> In fact it is very possible to
> write code which works portably: by refraining from passing 0.
But that entire paragraph is talking about the impossibility to call
realloc(p,0) portably. Of course if you call realloc(p,n?:1) it works,
because you've avoided the case altogether.
> Regardless of what action is taken here on the standards or
> documentation, that's already been necessary for a long time, and will
> continue to be necessary for a long time, because of the existence of
> implementations on which passing 0 has inconsistent results.
>
> I would suggest something more like:
>
> The behavior of realloc(p, 0) in glibc doesn’t conform to any of
> C99, C11, POSIX.1‐2001, POSIX.1‐2008, POSIX.1‐2017, or
> POSIX.1‐2024. C11 was amended in 2017 to allow the glibc
> behavior [insert description of exactly how that was done, I
> forget] and C23 followed up by making the behavior explicitly
> undefined.
>
> In particular, this text is purely matters of fact, no statement of
> your or my preferred future outcome or disagreement with what
> happened.
>
> I would also move it to CONFORMANCE rather than VERSIONS since
> VERSIONS is normally about differences between versions of the
> implementation being described, not conformance requirement
> differences between versions of the standard.
Agree. I've moved it to STANDARDS.
> > +BUGS
> > + Programmers would naturally expect that realloc(p, size) is con‐
> > + sistent with free(p) and malloc(size). This is not explicitly
> > + required by POSIX.1‐2024 or C11, but all conforming implementa‐
> > + tions are consistent with that.
>
> This has not historically been a conformance requirement and it is not
> one now. Because the behavior is undefined, arbitrarily-inconsistent
> behavior is conforming.
This section is about bugs, not about standards. The expectation of
programmers is what matters. Since programmers do
new = realloc(old, size);
if (new == NULL)
goto fail;
the glibc implementation is causing bugs in user programs, and thus has
a bogus implementation. Especially, when it deviates from common
historical implementations, which supported the idiom shown above.
This is enough to claim it's a bug in glibc.
> It's possible to read this as not stating a conformance requirement,
> just a matter of fact that all implementations which conform(ed to
> past versions of the standard) happened to also be consistent here.
Yes.
> But in that case I would very much prefer if you make it clear by just
> saying that they're consistent on [some explicit list or description
> of the class of implementations you've reviewed to have this
> property].
I don't fully understand this suggestion. Please clarify.
>
> > + The glibc implementation of realloc() is not consistent with
> > + that, and as a consequence, it is dangerous to call
> > + realloc(p, 0) in glibc.
>
> It's not dangerous if you know what it's doing. Rather it's
> non-portable. It does something predictable that you can use safely,
> but the way you use it safely is different from other, more consistent
> implementations in a way that can be a footgun.
It is dangerous, because programmers don't expect the glibc behavior.
Please show me a piece of code calling realloc(3) from glibc that does
something like this:
new = realloc(old, size);
if (new == NULL) {
if (errno == ENOMEM)
free(old);
goto fail;
}
free(new);
It is only unnecessary if you know for sure 'size' won't ever be 0, but
I bet there's code out there where size might be 0 and they're not doing
this. If they're freeing 'old' on NULL without checking for ENOMEM,
they're causing a double-free. If they're using old on NULL without
checking for ENOMEM, they're causing a use-after-free.
That *is* dangerous.
>
> > + A trivial workaround for glibc is calling it as
> > + realloc(p, size?size:1).
>
> It should probably be noted that use of such a workaround sacrifices
> the ability to diagnose logic errors (via sanitizers, valgrind, etc.)
> where 1 byte is written to allocated memory that was not intended to
> have any accessible bytes of storage.
I would note it for n+1, but since n?n:1 would only hide them for the
case where size is 0, I find it less problematic. I think adding such
text might put off programmers from using this, which would be
counterproductive. So, I hope they realize about it without writing it.
Have a lovely day!
Alex
--
<https://www.alejandro-colomar.es/>
signature.asc
Description: PGP signature
