C Language Standards Update – Zero-size Reallocations are Undefined Behavior

[Editor’s Note: Robert Seacord of NCC Group is a longstanding member of the C Standards Committee. In this blog post, he outlines a recently adopted change he proposed to the C Language Standard, to help eliminate double-free vulnerabilities being introduced to C code as a result of zero-sized reallocations of memory.]


by Robert Seacord

The C Standard Library realloc function has proven to be more than a little problematic.  The realloc function increases or decreases the size of previously allocated storage and so naturally takes a pointer to memory from a previous allocation and a new size as arguments.  If the function succeeds, it returns a pointer to newly allocated storage and frees the old memory.  If the memory could not be allocated, the function fails and returns a null pointer.  There is an interesting edge case however.  What happens when the size of the new allocation is zero bytes?  The C Standards Committee originally intended that that this operation would succeed and return a pointer to a zero-byte allocation.  In other words, the function would only return a null pointer when an operation fails. However, many implementations including glibc,  AIX, and zOS diverged from the intent of the C Standard (to be fair, could have been more clearly stated).  Some implementations would always return a null pointer, even when the allocation might have succeeded.  Some implementations (including glibc) would actually return a null pointer but still free the pointer to the old memory.  This behavior could easily leave lead to double-free vulnerabilities for zero-sized reallocations if the developer attempted to free the old memory a second time, because this was typically necessary when a reallocation failed.  Even the Linux man page contained a double-free vulnerability.  

To address this problem, the C Committee initially decided to expand the behavior of the realloc function to cover all the possible implementations.  The goal was to not require these implementations to change, and as a consequence, break existing code that worked correctly for the existing (but non-standard) behavior.  Invoking realloc with a size argument equal to zero was made an obsolescent feature.  However, these changes made the realloc function useless for zero byte allocations, which were troublesome at best.  As a result of the on-going confusion with this function, Robert Seacord submitted the proposal n2464, Zero-size Reallocations are Undefined Behavior which was unanimously adopted by the committee at a virtual meeting in Spring 2020.  Making this behavior undefined continues to allow existing implementations to do as they please, but provides a clear warning to developers to guard against zero-byte reallocations.


Other use and misuse cases for realloc are described in my new book from No Starch Press,  Effective C: An Introduction to Professional C Programming:

https://nostarch.com/Effective_C