Undefined behavior 179 states that the behavior of a program is undefined when
The pointer argument to the
free
orrealloc
function does not match a pointer earlier returned by a memory management function, or the space has been deallocated by a call tofree
orrealloc
.
Freeing memory that is not allocated dynamically can result in heap corruption and other serious errors. Do not call free()
on anything other than a pointer returned by a dynamic memory allocation function, such as malloc()
, calloc()
, realloc()
, or aligned_alloc()
.
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.
This rule does not apply to null pointers. The C Standard guarantees that if free()
is passed a null pointer, no action occurs.
Noncompliant Code Example
This noncompliant code example sets c_str
to reference either dynamically allocated memory or a statically allocated string literal depending on the value of argc
. In either case, c_str
is passed as an argument to free()
. If anything other than dynamically allocated memory is referenced by c_str
, the call to free(c_str)
is erroneous.
#include <stdlib.h> #include <string.h> #include <stdio.h> enum { MAX_ALLOCATION = 1000 }; int main(int argc, const char *argv[]) { char *c_str = NULL; size_t len; if (argc == 2) { len = strlen(argv[1]) + 1; if (len > MAX_ALLOCATION) { /* Handle error */ } c_str = (char *)malloc(len); if (c_str == NULL) { /* Handle error */ } strcpy(c_str, argv[1]); } else { c_str = "usage: $>a.exe [string]"; printf("%s\n", c_str); } free(c_str); return 0; }
Compliant Solution
This compliant solution eliminates the possibility of c_str
referencing memory that is not allocated dynamically when passed to free()
:
#include <stdlib.h> #include <string.h> #include <stdio.h> enum { MAX_ALLOCATION = 1000 }; int main(int argc, const char *argv[]) { char *c_str = NULL; size_t len; if (argc == 2) { len = strlen(argv[1]) + 1; if (len > MAX_ALLOCATION) { /* Handle error */ } c_str = (char *)malloc(len); if (c_str == NULL) { /* Handle error */ } strcpy(c_str, argv[1]); } else { printf("%s\n", "usage: $>a.exe [string]"); return -1; } free(c_str); return 0; }
Noncompliant Code Example (realloc()
)
In this noncompliant example, the pointer parameter to realloc()
, buf
, does not refer to dynamically allocated memory:
#include <stdlib.h> enum { BUFSIZE = 256 }; void f(void) { char buf[BUFSIZE]; char *p = (char *)realloc(buf, 2 * BUFSIZE); if (p == NULL) { /* handle error */ } }
Compliant Solution (realloc()
)
In this compliant solution, buf
refers to dynamically allocated memory:
#include <stdlib.h> enum { BUFSIZE = 256 }; void f(void) { char *buf = (char *)malloc(BUFSIZE * sizeof(char)); char *p = (char *)realloc(buf, 2 * BUFSIZE); if (p == NULL) { /* handle error */ } }
Note that realloc()
will behave properly even if malloc()
failed, because when given a null pointer, realloc()
behaves like a call to malloc()
.
Risk Assessment
The consequences of this error depend on the implementation, but they range from nothing 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
Tool | Version | Checker | Description |
---|---|---|---|
Can detect some violations of this rule | |||
2017.07 | BAD_FREE | Identifies calls to | |
2024.3 | FNH.MIGHT | ||
9.7.1 | 483 S | Fully implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C Secure Coding Standard | MEM31-C. Free dynamically allocated memory when no longer needed |
CERT C++ Secure Coding Standard | MEM34-CPP. Only free memory allocated dynamically |
ISO/IEC TS 17961 | Reallocating or freeing memory that was not dynamically allocated [xfree] |
MITRE CWE | CWE-590, Free of invalid pointer not on the heap |
Bibliography
[Seacord 2013] | Chapter 4, "Dynamic Memory Management" |
[ISO/IEC 9899:2011] | Annex J, subclause J.2, "Undefined Behavior" |