Dangling pointer
| Vulnerability potential | High |
| DDoS potential | Medium |
The memory by the pointer might be used after freeing
Impact
A dangling pointer still holds the address of an object whose lifetime has
ended — memory that was freed/deleted, a stack frame that has returned, or a
container element that was reallocated. Dereferencing it is use-after-free
(CWE-416), which is undefined behaviour. In the best case the old contents are
still intact and the program seems to work; more often the allocator has reused
that memory for an unrelated object, so the read returns another object’s data
and the write corrupts it. Because the freed region may hold allocator metadata
or a new object’s vtable, the corruption frequently leads to a crash or to fully
controllable behaviour — and the failure is intermittent, depending entirely on
allocation timing.
Vulnerability potential
Use-after-free is among the most weaponised memory-safety defects, routinely exploited in browsers and kernels.
- After the object is freed, an attacker who can trigger a same-sized allocation can place controlled data where the stale pointer points (heap “grooming”/feng-shui), so the subsequent use operates on attacker bytes.
- If the freed object contained a function pointer or C++ vtable, replacing it yields control-flow hijack and remote code execution.
- A use-after-free read discloses whatever now occupies the memory (info leak, useful for defeating ASLR).
- Even without a controlled reuse, the resulting corruption commonly crashes the process, a Denial-of-Service vector.
Technical details
free/delete returns the memory to the allocator but does not change any
pointer that referenced it. Every such pointer is now dangling. The window of
exploitability opens the moment the memory is reused — by the same thread or by
another allocation anywhere in the program.
Sources of dangling pointers
Heap: using a pointer after free/delete, or keeping a second alias after
freeing through the first. Stack: returning the address of a local variable, or
keeping a pointer to a local after its scope ends. Containers: holding a pointer
or iterator into a std::vector after it reallocates on growth, or into a
container element after erase. C strings: keeping a pointer into a buffer that
was realloc‘d to a new address.
Double-free and friends
A dangling pointer passed back to free is a double-free, a closely related and
equally exploitable corruption of allocator state.
Mitigation idioms
Set pointers to NULL/nullptr immediately after freeing (turns a UAF into a
detectable null deref), and prefer ownership models — RAII, std::unique_ptr,
std::shared_ptr/weak_ptr — that tie lifetime to scope.
Catching the issue
AddressSanitizer
-fsanitize=address quarantines freed memory and reports use-after-free and
use-after-return (ASAN_OPTIONS=detect_stack_use_after_return=1) with both the
allocation and the free stack traces. This is the single most effective tool.
Other dynamic tools
Valgrind/Memcheck flags reads/writes to freed blocks. MemorySanitizer catches some uses of uninitialised reused memory. GWP-ASan provides low-overhead sampling detection in production.
Static analysis
Clang Static Analyzer, Coverity, Cppcheck, and PVS-Studio detect many
use-after-free paths, including return-of-local-address (also a plain compiler
warning: -Wreturn-local-addr, -Wdangling-pointer in recent GCC).
Design
Use smart pointers and clear ownership; avoid raw owning pointers; null out freed pointers; never return addresses of locals; re-fetch pointers/iterators after any container operation that can reallocate.
How to reproduce
Compile with -fsanitize=address and run; ASan reports a heap-use-after-free,
showing where the block was freed and where it was used.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p = malloc(sizeof *p);
*p = 42;
free(p); /* p is now dangling */
/* use-after-free: reads/writes memory that no longer belongs to us */
*p = 7;
printf("%d\n", *p);
return 0;
}