Freeing memory that is not allocated dynamically can lead to serious errors. The specific consequences of this error depend on the compiler, but they range from nothing to abnormal program termination. Regardless of the compiler, avoid calling free()
on anything other than a pointer returned by a dynamic-memory allocation function, such as malloc()
, calloc()
, or realloc()
.
A similar situation arises when realloc()
is supplied a pointer to non-dynamically allocated memory. The realloc()
function is used to resize a block of dynamic memory. If realloc()
is supplied a pointer to memory not allocated by a memory allocation function, such as malloc()
, the program may terminate abnormally.
Noncompliant Code Example
This noncompliant code example sets str
to reference either dynamically allocated memory or a statically allocated string literal depending on the value of argc
. In either case, str
is passed as an argument to free()
. If anything other than dynamically allocated memory is referenced by str
, the call to free(str)
is erroneous.
enum { MAX_ALLOCATION = 1000 }; int main(int argc, const char *argv[]) { char *str = NULL; size_t len; if (argc == 2) { len = strlen(argv[1])+1; if (len > MAX_ALLOCATION) { /* Handle Error */ } str = (char *)malloc(len); if (str == NULL) { /* Handle Allocation Error */ } strcpy(str, argv[1]); } else { str = "usage: $>a.exe [string]"; printf("%s\n", str); } /* ... */ free(str); return 0; }
Compliant Solution
In the compliant solution, the program has been modified to eliminate the possibility of str
referencing non-dynamic memory when it is supplied to free()
.
enum { MAX_ALLOCATION = 1000 }; int main(int argc, const char *argv[]) { char *str = NULL; size_t len; if (argc == 2) { len = strlen(argv[1])+1; if (len > MAX_ALLOCATION) { /* Handle Error */ } str = (char *)malloc(len); if (str == NULL) { /* Handle Allocation Error */ } strcpy(str, argv[1]); } else { printf("%s\n", "usage: $>a.exe [string]"); return -1; } /* ... */ free(str); return 0; }
Risk Assessment
Freeing or reallocating memory that was not dynamically allocated can lead to arbitrary code execution if that memory is reused by malloc()
.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MEM34-C |
high |
likely |
medium |
P18 |
L1 |
Automated Detection
The Coverity Prevent BAD_FREE checker identifies calls to free()
where the argument is a pointer to a function or an array. Coverity Prevent cannot discover all violations of this rule, so further verification is necessary.
Klocwork Version 8.0.4.16 can detect violations of this rule with the FNH.MIGHT, FNH.MUST, FUM.GEN.MIGHT, FUM.GEN.MUST, FUM.ZERO.MIGHT, and FUM.ZERO.MUST checkers.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC 9899:1999]] Section 7.20.3, "Memory management functions"
[[Seacord 05]] Chapter 4, "Dynamic Memory Management"
MEM33-C. Use the correct syntax for flexible array members 08. Memory Management (MEM)