A buffer overflow is a memory-safety vulnerability in which a program writes data beyond the boundaries of a fixed-size memory region, overwriting adjacent memory that may hold other variables, heap metadata or control data such as return addresses. In cybersecurity it is one of the oldest and most consequential classes of vulnerabilities, cataloged as CWE-120 and CWE-787, and it remains a common root cause of remote code execution and privilege escalation.
Buffer overflows arise mainly in languages such as C and C++ that perform no automatic bounds checking. When an attacker controls the overflowing data, the corruption can be shaped to change program behavior or execute injected code, which turns a simple programming error into a serious security flaw.
How a buffer overflow corrupts memory
A buffer is a contiguous block of memory reserved for a known number of elements, such as a 64-byte array for a user name. An overflow occurs when code copies more data than the buffer can hold, typically because the length check is missing, uses the wrong unit, or is computed from an attacker-controlled value. Functions such as strcpy, gets and unbounded sprintf are classic sources because they write until a terminator appears rather than until a limit is reached.
What gets corrupted depends on where the buffer lives. On the stack, local buffers sit near saved frame pointers and the return address, so an overflow can redirect execution when the function returns. On the heap, overflows corrupt neighboring objects, function pointers or allocator metadata, which attackers chain into arbitrary write primitives.
The table below compares the main variants.
| Type | Memory region | Typical target | Related weakness |
|---|---|---|---|
| Stack-based overflow | Call stack | Return address, saved registers | CWE-121 |
| Heap-based overflow | Dynamic heap | Adjacent objects, allocator metadata | CWE-122 |
| Off-by-one overflow | Stack or heap | One byte such as a frame pointer | CWE-193 |
| Buffer over-read | Any | Disclosure of adjacent secrets | CWE-126 |
| Global or static overflow | Data segment | Neighboring global variables | CWE-787 |
From overflow to exploitation
Early exploits placed shellcode in the overflowing buffer and overwrote the return address to jump into it. Modern systems block that approach with several mitigations, so attackers now combine an overflow with an information leak to defeat randomization and then use return-oriented programming, chaining short existing instruction sequences instead of injecting new code.
Not every overflow is exploitable for code execution. Depending on the context, the impact ranges from a crash and denial of service, through data corruption or information disclosure, to full remote code execution with the privileges of the process. Severity scores in CVSS therefore vary widely for the same weakness class.
Over-reads deserve attention as well: they do not corrupt memory but can leak keys, passwords or pointers, as several well-known TLS library flaws demonstrated.
Attackers rarely find overflows by reading code alone. They diff security patches, fuzz network parsers and file format handlers, and examine crash reports. Parsers of untrusted input, such as image decoders, protocol stacks, firmware web interfaces and font renderers, are therefore the components where overflows most often turn into practical attacks, and they deserve the strongest scrutiny.
Mitigations and their limits
Operating systems and compilers deploy layered exploit mitigations that make overflows harder to exploit but do not remove the underlying bug. Each mitigation addresses a specific exploitation step.
| Mitigation | What it does | Known bypass or limit |
|---|---|---|
| Stack canaries | Detect overwritten return paths before return | Leaks of the canary value, heap targets |
| DEP or NX | Marks data memory as non-executable | Return-oriented programming |
| ASLR | Randomizes memory layout | Information leaks, low entropy on 32-bit |
| Control-flow integrity | Restricts indirect call and return targets | Coarse policies, data-only attacks |
| FORTIFY_SOURCE | Adds checked versions of copy functions | Only when sizes are known at compile time |
| Hardware tagging | Associates pointers with memory tags | Limited hardware support, probabilistic |
Because every mitigation has documented bypasses, the durable fix is eliminating the out-of-bounds write itself, either in code or by changing the language.
Preventing buffer overflows in development
Prevention combines safer languages, safer interfaces and systematic testing. Memory-safe languages such as Rust, Go, Java and C# perform bounds checks or prohibit unchecked pointer arithmetic, which removes the class almost entirely outside explicitly unsafe code. Government agencies and large vendors now recommend memory-safe language roadmaps for new code.
| Stage | Measure | Effect |
|---|---|---|
| Design | Choose a memory-safe language | Removes most overflow classes |
| Coding | Use bounded APIs and length-carrying types | Fewer unchecked copies |
| Build | Enable warnings, fortification and hardening flags | Earlier detection, harder exploitation |
| Testing | Fuzzing with AddressSanitizer | Finds overflows before release |
| Review | Static analysis and focused code review | Catches missing or wrong checks |
Fuzzing combined with sanitizers has proven particularly effective: continuous fuzzing services for open-source projects have found thousands of memory-safety bugs. Integer handling deserves equal care, because an integer overflow in a size calculation frequently produces an undersized allocation that later overflows.
Buffer overflow among related vulnerability classes
Buffer overflows belong to the wider family of memory corruption vulnerabilities, and responders often need to distinguish them precisely for triage and patching.
| Weakness | Root cause | Relation to buffer overflow |
|---|---|---|
| Use-after-free | Access to memory after release | Temporal rather than spatial error |
| Integer overflow | Arithmetic wraps around | Often causes the overflow |
| Format string bug | User input used as format string | Different mechanism, similar impact |
| Type confusion | Object treated as wrong type | Can produce out-of-bounds access |
For vulnerability management, the distinction matters less than the exposure and reachability of the flawed code. A heap overflow in an internet-facing service with a public exploit, listed in CISA KEV, warrants emergency patching, while the same weakness in an offline tool can usually wait for a regular update cycle.
The idea in brief
A buffer overflow happens when a program tries to put more data into a box than the box can hold. The extra data does not disappear. It spills into the boxes next to it and overwrites what was stored there.
If one of those neighboring boxes holds instructions about what the program should do next, an attacker can replace them with their own instructions. That is why a simple size mistake can become a serious security hole.
A practical scenario
A manufacturer of industrial network gateways receives a report that a crafted HTTP header crashes the device’s web interface. Analysis shows that the firmware copies the header into a 256-byte stack buffer with strcpy, and the device runs without stack canaries or ASLR.
A researcher demonstrates that the crash can be turned into remote code execution as root. The vendor replaces the copy with a length-checked routine, enables compiler hardening, adds fuzzing to its build pipeline and ships a firmware update. A CVE is published through coordinated disclosure, and operators are advised to restrict management interfaces to trusted networks until they patch.