Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <l47kg74zm6wukxn7hm3lot73bt5huhtal32fhpj25aozfncuw7@qgf5o3m5do5o>
Date: Fri, 20 Jun 2025 13:58:23 +0200
From: Alejandro Colomar <alx@...nel.org>
To: Vincent Lefevre <vincent@...c17.net>, Eric Blake <eblake@...hat.com>, 
	Rich Felker <dalias@...c.org>, enh <enh@...gle.com>, Florian Weimer <fweimer@...hat.com>, 
	Adhemerval Zanella Netto <adhemerval.zanella@...aro.org>, musl@...ts.openwall.com, libc-alpha@...rceware.org, 
	Joseph Myers <josmyers@...hat.com>, наб <nabijaczleweli@...ijaczleweli.xyz>, 
	Paul Eggert <eggert@...ucla.edu>, Robert Seacord <rcseacord@...il.com>, 
	Bruno Haible <bruno@...sp.org>, bug-gnulib@....org, JeanHeyd Meneide <phdofthehouse@...il.com>, 
	Thorsten Glaser <tg@...bsd.de>
Subject: Re: Re: BUG: realloc(p,0) should be consistent with malloc(0)

Hi Vincent,

On Fri, Jun 20, 2025 at 04:11:23AM +0200, Vincent Lefevre wrote:
> On 2025-06-20 01:37:58 +0200, Alejandro Colomar wrote:
> > On Thu, Jun 19, 2025 at 01:31:06PM -0500, Eric Blake wrote:
> > > On Wed, Jun 18, 2025 at 09:04:02PM +0200, Alejandro Colomar wrote:
> > > > 	glibc doesn't conform to:
> > > > 		-  SysIII
> > > > 		-  SysV
> > > > 		-  SysVr2
> > > > 		-  SysVr3
> > > > 		-  SVID Issue 2
> > > > 		-  SVID Issue 3
> > > > 		-  The X/Open System V Specification
> > > > 		-  ISO C99
> > > 
> > > Here, section 7.20.3.4 is relevant. In there, I see wording "If ptr is
> > > a null pointer, the realloc function behaves like the malloc function
> > > for the specified size." but NO wording about when ptr is non-null but
> > > size is 0.  As best I can tell, silence on the part of C99 means that
> > > the standard is unspecified, and therefore glibc can do whatever it
> > > wants and still claim compliance.  But I'm open to correction if you
> > > can quote the exact statement for why you claim glibc is non-compliant
> > > here.
> > 
> > <https://port70.net/~nsz/c/c99/n1256.html#7.20.3.4>
> > 
> > I'll quote the entire text:
> > 
> > 	Description
> > 
> > 	2	The realloc function
> > 		deallocates the old object pointed to by ptr and
> > 		returns a pointer to a new object that
> > 		has the size specified by size.
> > 		[...]  // talks about the contents
> > 
> > 	3	If ptr is a null pointer, [...].
> > 		Otherwise,
> > 		if ptr does not match a pointer earlier returned by
> > 		the calloc, malloc, [...], the behavior is undefined.
> > 		If memory for the new object cannot be allocated,
> > 		the old object is not deallocated and its value is unchanged.
> > 
> > 	Returns
> > 
> > 	4	The realloc function returns a pointer to the new object
> > 		(which may have the same value as a pointer to the old object),
> > 		or a null pointer if the new object could not be allocated. 
> > 
> > IMO, paragraph 4 rules out the possibility of returning a null pointer
> > on success.
> 
> Perhaps not if size is 0, see below.
> 
> > Also, while it doesn't specify what happens in the case of size 0
> > explicitly, it mentions in paragraph 2 what happens for all sizes:
> > it returns a pointer to a new object that has the size specified by
> > size --which in this case is 0 bytes--.
> 
> You should also consider the end of 7.20.3p1 (which applies to calloc,
> malloc and realloc):
> 
>   If the size of the space requested is zero, the behavior is
>   implementation-defined: either a null pointer is returned, or the
>   behavior is as if the size were some nonzero value, except that
>   the returned pointer shall not be used to access an object.

Right.  I missed that part.

So, C99 and C11 allow realloc(p,0) to return a null pointer.

> 
> Consider the case "a null pointer is returned" with realloc(non_null,0).
> I can see 2 possible interpretations:
> 
> 1. This is always a failure (corresponding to "a null pointer if the
> new object could not be allocated" in 7.20.3.4p4). But I doubt that
> this is the intended behavior, as there would be major memory leaks
> in practice with such an implementation and would make such a call
> useless.
> 
> 2. This means that the memory is entirely freed, which is a success.
> This makes your assumption "paragraph 4 rules out the possibility of
> returning a null pointer on success" above wrong. However, in order
> to know whether a null pointer means a success (memory entirely freed)
> or a failure (for the case "the behavior is as if the size were some
> nonzero value"), the application would need to know which kind of
> implementation it is (e.g. guessed by tools like configure tests).

To disambiguate, we need to read

<https://port70.net/~nsz/c/c99/n1256.html#7.20.3.4>

First p4:

	4	The realloc function returns a pointer to the new object
		(which may have the same value as a pointer to the old object),
		or a null pointer if the new object could not be allocated.

So, a null pointer, which is allowed for r(p,0), means that "the new
object could not be allocated".

And then we read the last sentence of p3:

	3	[...]
		If memory for the new object cannot be allocated,
		the old object is not deallocated and its value is unchanged.

So, the input pointer must not be freed.

I'd say glibc is non-conforming, even if this could possibly have been
unintended by the C Committee.


Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es/>

Download attachment "signature.asc" of type "application/pgp-signature" (834 bytes)

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.