Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aFbGbVd327ZUrdrA@voyager>
Date: Sat, 21 Jun 2025 16:49:17 +0200
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Cc: "Maciej W. Rozycki" <macro@...hat.com>, libc-alpha@...rceware.org,
	bug-gnulib@....org,
	наб <nabijaczleweli@...ijaczleweli.xyz>,
	Douglas McIlroy <douglas.mcilroy@...tmouth.edu>,
	Paul Eggert <eggert@...ucla.edu>,
	Robert Seacord <rcseacord@...il.com>,
	Elliott Hughes <enh@...gle.com>, Bruno Haible <bruno@...sp.org>,
	JeanHeyd Meneide <phdofthehouse@...il.com>,
	Rich Felker <dalias@...c.org>,
	Adhemerval Zanella Netto <adhemerval.zanella@...aro.org>,
	Joseph Myers <josmyers@...hat.com>,
	Florian Weimer <fweimer@...hat.com>,
	Andreas Schwab <schwab@...e.de>, Thorsten Glaser <tg@...bsd.de>,
	Eric Blake <eblake@...hat.com>,
	Vincent Lefevre <vincent@...c17.net>,
	Mark Harris <mark.hsj@...il.com>,
	Collin Funk <collin.funk1@...il.com>,
	Wilco Dijkstra <Wilco.Dijkstra@....com>, DJ Delorie <dj@...hat.com>,
	Cristian Rodríguez <cristian@...riguez.im>,
	Siddhesh Poyarekar <siddhesh@...plt.org>,
	Sam James <sam@...too.org>, Mark Wielaard <mark@...mp.org>,
	Martin Uecker <ma.uecker@...il.com>,
	Christopher Bazley <chris.bazley.wg14@...il.com>,
	eskil@...ession.se
Subject: Re: Re: alx-0029r1 - Restore the traditional realloc(3)
 specification

Am Sat, Jun 21, 2025 at 04:07:54AM +0200 schrieb Alejandro Colomar:
> I honestly still don't see the point in the camp returning NULL.  The
> only reason it hasn't died, I think, is because of fear of breaking
> existing code, but I don't see anyone asking for that behavior.
> 

I invert the question: What is the point of requesting zero bytes? If
you just want a pointer you cannot deref, but can validly plug into both
realloc() and free(), I have this perfectly good null pointer right
here. You can even statically initialize your variables with it. And you
can easily tell it apart from pointers you can dereference.

I see malloc(0) as an error. According to all standards I could get my
hands on, the argument to malloc is supposed to be the size of an
object, and in C, there are no objects without type, and no zero-sized
types. Maybe that's different in C++, I don't know. I have read a bit of
C code in my life, and have written some as well, and debugged even more
of it. I cannot recall an instance of anyone ever requesting to allocate
zero bytes except in error (e.g. uncaught overflow).

Indeed, a strict reading of the spec would be that the argument must be
the result of a sizeof expression, and the common idiom

A *a = malloc(sizeof (A) + sizeof (B));
B *b = (B *)(a + 1);

is undefined. And indeed, it potentially crashes on strict-alignment
architectures if alignof(B) > alignof(A).

Back to zero-sized allocations: The fact that they were traditionally
supported on UNIX means nothing if they were always undefined. At that
point it just becomes a quirk of the implementation, but nothing an
application should depend on.

The C89 mandate to free the pointer in case of zero-sized realloc (which
I read as a command to *only* free the pointer and not do anything else)
seems actively harmful: If an application can be tricked into doing
that, and an implementation chooses to return the now freed pointer
(since realloc must return /something/), then the application now holds
a pointer it thinks is still valid, but is actually dangling.

The way C89 (or rather FIPS160, which is the version I've read) has
added the realloc-0-frees mandate, it looks like a badly thought through
afterthought. But then, C89 also contains sprintf() and gets(), so badly
thought through afterthoughts are certainly not a novelty to that
particular writ.

All standards after it have tinkered with the semantics of zero-sized
allocation, to the point that C23 just made it explicitly undefined. As
application developer, what inference do I draw from this, except to
avoid zero-sized allocation like the plague? If anyone actually writes
"realloc(p, 0)" intending it to be the same as "free(p)", I would tell
them to then write what they mean and stop being so clever.

As implementation developer, I would therefore treat these requests as
errors, and do the appropriate thing: Return the error value and set
errno to EINVAL (and have no further side effects). And such an
implementation conforms to everything from C99 onwards.

Ciao,
Markus

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.