Buffer overflow

On this page 7

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.

TypeMemory regionTypical targetRelated weakness
Stack-based overflowCall stackReturn address, saved registersCWE-121
Heap-based overflowDynamic heapAdjacent objects, allocator metadataCWE-122
Off-by-one overflowStack or heapOne byte such as a frame pointerCWE-193
Buffer over-readAnyDisclosure of adjacent secretsCWE-126
Global or static overflowData segmentNeighboring global variablesCWE-787
Main types of buffer overflow

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.

MitigationWhat it doesKnown bypass or limit
Stack canariesDetect overwritten return paths before returnLeaks of the canary value, heap targets
DEP or NXMarks data memory as non-executableReturn-oriented programming
ASLRRandomizes memory layoutInformation leaks, low entropy on 32-bit
Control-flow integrityRestricts indirect call and return targetsCoarse policies, data-only attacks
FORTIFY_SOURCEAdds checked versions of copy functionsOnly when sizes are known at compile time
Hardware taggingAssociates pointers with memory tagsLimited hardware support, probabilistic
Common exploit mitigations

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.

StageMeasureEffect
DesignChoose a memory-safe languageRemoves most overflow classes
CodingUse bounded APIs and length-carrying typesFewer unchecked copies
BuildEnable warnings, fortification and hardening flagsEarlier detection, harder exploitation
TestingFuzzing with AddressSanitizerFinds overflows before release
ReviewStatic analysis and focused code reviewCatches missing or wrong checks
Prevention measures by development stage

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 overflows belong to the wider family of memory corruption vulnerabilities, and responders often need to distinguish them precisely for triage and patching.

WeaknessRoot causeRelation to buffer overflow
Use-after-freeAccess to memory after releaseTemporal rather than spatial error
Integer overflowArithmetic wraps aroundOften causes the overflow
Format string bugUser input used as format stringDifferent mechanism, similar impact
Type confusionObject treated as wrong typeCan produce out-of-bounds access
Related memory-safety weaknesses

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.