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: