Evaluating pointers into memory that have been deallocated by a memory management function, including dereferencing, acting as an operand of an arithmetic operation, type casting, or using the pointer as the right-hand side of an assignment, is undefined behavior. Pointers to memory that have been deallocated are referred to as called dangling pointers. Accessing a dangling pointer can result in exploitable vulnerabilities.
...
Page properties | ||
---|---|---|
| ||
This rule could probably stand to cover memory which has yet to be allocated. For instance:
This isn't really covered by EXP53-CPP. Do not read uninitialized memory because it has nothing to do with reading an unitialized uninitialized value. |
Noncompliant Code Example (new
and delete
)
In this noncompliant code example, s
is dereferenced after it has been deallocated. If this access results in a write-after-free, the vulnerability can be exploited to run arbitrary code with the permissions of the vulnerable process and are seldom this obvious. Typically, dynamic memory allocations and deallocations are far removed, making it difficult to recognize and diagnose such problems.
...
In this compliant solution, the dynamically allocated memory isn't is not deallocated until it is no longer required:
...
Compliant Solution (Automatic Storage Duration)
When possible, it is preferred to use automatic storage duration instead of dynamic storage duration. Since s
is not required to live beyond the scope of f()
, this compliant solution uses automatic storage duration to limit the lifetime of s
to the scope of f()
:
...
In this compliant solution, the lifetime of the buff
object extends past the point at which the memory managed by the object is accessed:
...
In this noncompliant code example, std::string::c_str()
is being called on a temporary std::string
object. The resulting pointer will point to released memory once the std::string
object is destroyed at the end of the assignment expression, resulting in undefined behavior when accessing elements of that pointer.
...
In this compliant solution, a local copy of the string returned by someStringReturningFunction()
is made to ensure that ensures the string str
will be valid when the call to displayString
is made:
...
In this noncompliant code example, an attempt is made to allocate zero bytes of memory through a call to operator new()
. If this request succeeds, operator new()
is required to return a nonnull non-null pointer value. However, according to the C++ Standard, [basic.stc.dynamic.allocation], paragraph 2 [ISO/IEC 14882-2014], attempting to indirect through such a pointer results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <new> void f() noexcept(false) { unsigned char *ptr = static_cast<unsigned char *>(::operator new(0)); *ptr = 0; // ... ::operator delete(ptr); } |
...
The compliant solution depends on programmer intent. If the programmer intended intends to allocate a single unsigned char
object, the compliant solution is to use new
instead of a direct call to operator new()
, as this compliant solution demonstrates:
Code Block | ||||
---|---|---|---|---|
| ||||
void f() noexcept(false) { unsigned char *ptr = new unsigned char; *ptr = 0; // ... delete ptr; } |
If the programmer intended intends to allocate zero bytes of memory (perhaps in order to obtain a unique pointer value that cannot be reused by any other pointer in the program , until it is properly released), then the compliant solution is to not attempt to instead of attempting to dereference the resulting pointer. Instead, ptr
is declared , the compliant solution is to declare ptr
as a void *
, which cannot be indirected through in a conforming implementation.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <new> void f() noexcept(false) { void *ptr = ::operator new(0); // ... ::operator delete(ptr); } |
...
Reading previously dynamically allocated memory after it has been deallocated can lead to abnormal program termination and denial-of-service attacks. Writing memory that has been deallocated can lead to the execution of arbitrary code with the permissions of the vulnerable process.
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
|
|
| |||||||
| USE_AFTER_FREE | Can detect the specific instances where memory is deallocated more than once or read/written to the target of a freed pointer | |||||||
5.0 | Double Free |
| |||||||
| UFM.DEREF.MIGHT |
| |||||||
| 51 D | Fully implemented | |||||||
|
|
|
...