The results of allocating zero bytes of memory using malloc()
, calloc()
, or realloc()
are implementation-defined. According to C99 Section 7.20.3 ISO/IEC 9899-1999:
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.
This includes all three standard memory allocation functions: malloc()
, calloc()
, and realloc()
. In cases where the memory allocation functions return a non-null pointer, using this pointer results in undefined behavior. Typically these pointer refer to a zero-length block of memory consisting entirely of control structures. Overwriting these control structures will damage the data structures used by the memory manager.
...
To ensure that zero is never passed as a size argument to malloc()
, a check must be made on size
size
is checked to ensure it is not zerohas a positive value.
Code Block | ||
---|---|---|
| ||
if (size <= 0) { /* Handle Error */ } list = malloc(size); if (list == NULL) { /* Handle Allocation Error */ } /* Continue Processing list */ |
...
The realloc()
function deallocates the old object and returns a pointer to a new object of a specified size. If memory for the new object cannot be allocated, the realloc()
function does not deallocate the old object and its value is unchanged. If the realloc() function returns NULL, failing to free the original memory will result in a memory leak. As a result, the following idiom is generally often recommended for reallocating memory:
...
However, this commonly recommended idiom has problems with zero length allocations. If the value of nsize
in this example is 0, the standard allows the option of either returning a null pointer or returning a pointer to an invalid (e.g., zero-length) object. In cases where the realloc()
function frees the memory but returns a null pointer, execution of the code in this example results in a double free.
Implementation Details
The realloc()
function for If this non-compliant code is compiled with gcc 3.4.6 and linked with libc 2.3.4, invoking realloc(0)
returns a non-null pointer to a zero-sized object (the same as malloc(0)
). However, the realloc()
function for both if the same code is compiled with either Microsoft Visual Studio Version 7.1 and or gcc version 4.1.0 return 0 , realloc(0)
returns a null pointer, --resulting in a double free on the call to free()
in this examplevulnerability.
Compliant Code Example
Do not pass a size argument of zero to the realloc()
function.
...