Path: csiph.com!weretis.net!feeder8.news.weretis.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: *rubeyes*: realloc(ptr, 0) is UB? Date: Tue, 23 Jan 2024 19:28:38 -0800 Organization: A noiseless patient Spider Lines: 79 Message-ID: <86r0i7e7fd.fsf@linuxsc.com> References: <20240116162506.143@kylheku.com> <20240117094759.508@kylheku.com> <9iYpN.354613$83n7.275953@fx18.iad> <86r0ifjbiw.fsf@linuxsc.com> <20240118112920.465@kylheku.com> <20240118144021.3@kylheku.com> <87r0iech8j.fsf@nosuchdomain.example.com> <87msszbb08.fsf@nosuchdomain.example.com> <86cytugvve.fsf@linuxsc.com> <87edeab85u.fsf@nosuchdomain.example.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: dont-email.me; posting-host="081b48eb4d739c8d0f1cd5168e73e868"; logging-data="1757645"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+WWIhSNIBtMlOJERy8bCY79GnVURJHRQY=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:72sy6VJEy+p5DLCjytoHPbjugnM= sha1:ySD05aZXN/8GdYaqoGvxZoUhO7I= Xref: csiph.com comp.lang.c:380748 Keith Thompson writes: > Tim Rentsch writes: > >> Keith Thompson writes: >> >>> Keith Thompson writes: [...] >>>> I think I would have *liked* to see C23 drop the special permission >>>> to return a null pointer for a requested size of zero. C11 says (and >>>> this applies to malloc, realloc, and all other allocation functions): >>>> [...] >>>> >>>> Note that malloc(0) or realloc(ptr, 0) can still fail and return >>>> a null pointer if no space can be allocated, so all allocations >>>> should still be checked. But with this proposed change, code >>>> could rely on realloc(ptr, 0) returning a non-null pointer *unless* >>>> available memory is critically low -- pretty much the same as in C11, >>>> except that a null pointer would be an indication that something >>>> is seriously wrong. >>>> >>>> (I remember seeing a discussion about making the behavior of >>>> realloc(ptr, 0) undefined. I'm making inquiries, and I'll follow >>>> up if I learn anything relevant.) >>> >>> I got a response from JeanHeyd Meneide. >>> >>> If realloc(ptr, 0) returns a null pointer there's no way to tell >>> whether allocation failed (and ptr has not been freed), or the >>> implementation returns a null pointer for zero-sized allocations >>> (and ptr has been freed). Some implementations set errno, but C >>> doesn't require it. (Let me mention in passing that there is a way to tell that should work in practice on any non-malicious implementation.) >> It's trivial to fix that problem: simply require implementations >> to define a preprocessor symbol about how the implementation >> works. Problem solved. >> >> (There are other instances of implementation-defined behavior >> that would benefit from analogous changes along these lines.) > > I tend to agree that such a preprocessor symbol would be an > improvement. > > I still think, as I wrote above, that removing the permission to > return a null pointer on a successful zero-sized allocation would > be a greater improvement. > > A preprocessor symbol makes it easier for programmers to work > around the potential difference between implementations. The > change I advocate would make it completely unnecessary. > > Except, of course, that most code would still have to allow for > pre-C26 behavior, even if the change were adopted in C26. That's > unavoidable in the absence of time machines. On the gripping > hand, since it seems that most existing implementations (well, all > of the few I've tried) return a non-null pointer for malloc(0), it > might be reasonable to ignore the few pre-C26 implementations that > return a null pointer. I have an observation worth mentioning. Using glibc (tested in Ubuntu), these assignments void *x = malloc( 0 ); void *y = malloc( 1 ); both return a non-null pointer. Following that, however, these calls void *xx = realloc( x, 0 ); void *yy = realloc( y, 0 ); both return a null pointer, and subsequent code shows that both x and y have indeed been deallocated. (Both gcc and clang give the same result, which isn't surprising since both are using glibc.)