Allocation of zero size block
| Vulnerability potential | Medium |
| DDoS potential | None |
Argument of malloc is 0, which is probably a mistake
Impact
malloc(0) (and calloc(0, n), realloc(p, 0)) is permitted by the C
standard but its result is implementation-defined: the call may return either a
null pointer or a unique, non-null pointer that must still be passed to
free yet points at zero usable bytes. A zero-size request almost always means
a length calculation produced 0 by mistake — an empty input, an underflowed
size - offset, a multiplication that wrapped, or a loop that never set the
count. Two opposite failure modes follow. If the program assumes malloc
returns non-null on success, the null return from a zero request is mistaken for
an out-of-memory failure or, worse, dereferenced. If the program assumes it got a
real buffer, it writes to a pointer that legally addresses nothing, producing an
immediate heap overflow.
Vulnerability potential
The danger is not the zero allocation itself but the corrupted size arithmetic that usually produces it, and the writes that follow.
- If the zero came from an integer overflow or underflow in a size computation
(
count * sizewrapping to 0,end - startgoing negative), any subsequent write using the intended larger length overflows the minimal/zero-byte allocation — a heap buffer overflow that is a common exploitation primitive. - Code that treats the legitimate
NULLfrommalloc(0)as success and dereferences it triggers a null-pointer access. - Inconsistent handling across platforms (null on one libc, non-null on another) yields bugs that only surface on some targets, complicating review.
Technical details
The standard (C11 7.22.3) says that if the requested size is zero the behavior is
implementation-defined: the return is either a null pointer or a pointer suitable
for free that may not be dereferenced.
glibc / musl
Return a unique non-null pointer (glibc returns the minimum chunk, 16/32 bytes of metadata-backed but zero usable bytes). Writing through it corrupts adjacent heap metadata.
Other implementations
Some embedded and historical allocators return NULL for a zero size, so the
same code path that “worked” elsewhere now looks like allocation failure.
realloc(p, 0) is even murkier: it may free p and return NULL, or
return a minimal block, so using its result as if p were resized is unsafe;
C23 deprecates this form.
Catching the issue
Static analysis
Clang Static Analyzer, Coverity, PVS-Studio and PC-lint warn on a
malloc/calloc whose size argument can be zero, and on use of a
possibly-null allocation result. Pair this with checks for the integer
overflow/underflow that usually feeds the zero size.
Runtime
AddressSanitizer catches a write into a zero-size allocation as a heap overflow,
and reports use of the realloc(p, 0) result. Defensively, validate sizes
before allocating: reject or special-case size == 0 explicitly rather than
relying on implementation-defined behavior, and always check the returned
pointer.
How to reproduce
Run under AddressSanitizer (-fsanitize=address); the write into the zero-byte
allocation is reported as a heap-buffer-overflow.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
size_t n = 0; /* came from a bad length calculation */
char *p = malloc(n); /* may return NULL or a 0-byte block */
printf("p = %p\n", (void *)p);
p[0] = 'x'; /* null deref or heap overflow */
free(p);
return 0;
}