What Is a Buffer Overflow?
A buffer overflow happens when a program writes past the end of a fixed-size memory buffer, corrupting adjacent data. How it works and how modern systems defend against it.
A buffer overflow occurs when a program writes more data into a fixed-size block of memory (a buffer) than it was allocated to hold, and the excess data spills into adjacent memory. In languages that don’t automatically check array bounds, nothing stops that write — the extra bytes simply overwrite whatever comes next, which might be another variable, a saved return address, or a piece of the program’s own control flow.
Why it happens
A buffer is just a fixed-size region of memory reserved to hold data — a character array, a fixed-length struct field, a network read buffer. In low-level languages like C and C++, writing to an array doesn’t automatically check whether the index is within bounds; the language trusts the programmer to get the size right. A classic example:
void greet(char *name) {
char buffer[16];
strcpy(buffer, name); // no bounds check
}
If name is longer than 15 characters plus a null terminator, strcpy keeps writing past the end of buffer, into whatever memory happens to sit next to it on the stack. Whether that’s harmless or catastrophic depends entirely on what’s stored there.
Stack overflows and control-flow hijacking
The most dangerous variant targets the stack, the region of memory used for function calls, local variables, and — critically — the return address that tells the CPU where to resume execution after the current function finishes. If an attacker can overflow a stack buffer with carefully crafted data, they can overwrite that return address with a pointer to their own injected code, so that when the function returns, the CPU jumps into the attacker’s payload instead of back to the caller.
This is the mechanism behind classic “stack smashing” exploits, and for decades it was one of the most common routes to full remote code execution in software written in memory-unsafe languages.
Heap overflows
The same overrun can happen on the heap, the region used for dynamically allocated memory. Heap overflows are generally harder to exploit than stack overflows because the layout is less predictable, but they can corrupt heap metadata or adjacent allocated objects — including function pointers stored in a struct — leading to crashes or, with enough control, code execution.
Defenses that exist today
Modern systems layer several mitigations rather than relying on any single fix:
- Bounds-checked languages. Languages like Rust, Go, Python, and Java check array and slice bounds at runtime (or, for Rust, largely at compile time) and raise an error instead of allowing an out-of-bounds write. Choosing a memory-safe language eliminates the entire bug class for new code.
- Stack canaries. The compiler inserts a known value between local buffers and the return address; if an overflow overwrites it, a check before the function returns detects the corruption and aborts instead of continuing execution.
- Address space layout randomization (ASLR). Randomizing where the stack, heap, and libraries are loaded in memory on each run makes it much harder for an attacker to reliably guess the address of injected code, since the same exploit payload can’t assume a fixed address across runs.
- Non-executable memory (DEP/NX). Marking stack and heap memory as non-executable prevents the CPU from running code an attacker managed to write into a data buffer, forcing exploit techniques to rely on already-executable code already present in the program instead.
- Bounds-checked standard library functions. Safer replacements for dangerous C functions —
strncpyinstead ofstrcpy,snprintfinstead ofsprintf— take an explicit length argument, so a call site can’t overflow the destination simply by being called with unexpectedly long input.
Why it still matters
Even with these mitigations widely deployed, buffer overflows haven’t disappeared. A huge amount of existing infrastructure — operating system kernels, network daemons, embedded firmware, and older C and C++ codebases — predates the languages and compiler protections that prevent this bug class by construction, and rewriting it all isn’t realistic in the short term. Buffer overflows also remain a common root cause behind zero-day vulnerabilities disclosed in widely used software, particularly in components that parse untrusted network input or file formats, where an attacker gets to choose exactly what bytes arrive.
Buffer overflows vs other memory-safety bugs
Buffer overflows belong to a broader family of memory-safety issues — use-after-free, double-free, and uninitialized-memory reads all share the same root cause: the language trusts the programmer’s bookkeeping instead of enforcing it. They’re conceptually distinct from injection-style vulnerabilities like SQL injection or XSS, which exploit a program correctly interpreting attacker-supplied data as code or query syntax rather than exploiting a raw memory-safety violation, though both categories ultimately stem from trusting input more than the code should.
The takeaway
A buffer overflow is a write that goes past the end of an allocated buffer into adjacent memory, and in memory-unsafe languages nothing stops it from happening. The historically severe cases hijack a function’s return address to redirect execution into attacker-controlled code. Modern defenses — bounds-checked languages, stack canaries, ASLR, and non-executable memory — have raised the bar significantly, but the bug class persists wherever old C and C++ code still parses untrusted input, which is why it remains a recurring category in vulnerability disclosures today.
Keep reading
Chisato · · 4 min read OCSP vs CRL: How Certificate Revocation Works
OCSP and CRL are the two mechanisms browsers use to check if a TLS certificate has been revoked before its expiry date. Here's how each works.
Chisato · · 4 min read What Is a Watering Hole Attack?
A watering hole attack compromises a site its targets already trust, then waits for victims to visit — rather than phishing them directly.
Chisato · · 4 min read What Is a Firewall? Network Security Explained
A firewall filters network traffic against a ruleset, blocking connections that don't match. How packet filters, stateful inspection, and NGFWs differ.