Stack-based buffer overflows are among the most iconic and historically important software vulnerabilities. They have powered everything from early worms to modern exploit chains, and despite decades of mitigations, they remain relevant anywhere unsafe languages and unchecked memory operations persist.
CWE-121 occurs when software writes data past the bounds of a stack-allocated buffer.
In practical terms:
The application overwrites memory on the call stack, potentially corrupting execution state.
This article breaks down how stack-based buffer overflows occur, why developers still introduce them, modern exploitation techniques, framework-specific mitigations, and secure coding patterns.
What Is a Stack-Based Buffer Overflow?
A stack-based buffer overflow happens when a fixed-size buffer allocated on the stack receives more data than it can hold.
Unsafe example:
void process(char *input) {
char buf[32];
strcpy(buf, input);
}
If input exceeds 32 bytes, the overflow extends past buf into adjacent stack memory.
That may overwrite:
- Local variables
- Saved frame pointer
- Return address
- Exception handlers
- Stack canaries
How Stack-Based Buffer Overflow Actually Works
The root issue is unchecked writes into memory allocated on the stack frame.
Attack Flow
- Function allocates stack buffer
- Oversized input is copied into buffer
- Write exceeds buffer boundary
- Adjacent stack data overwritten
- Program crashes or execution is hijacked
Visual: Stack Overflow Memory Layout
Why Developers Still Get Stack Overflows Wrong
Unsafe Copy Functions
Classic dangerous APIs remain common:
strcpystrcatsprintfgets- Unbounded
scanf
Miscalculated Bounds
Developers validate lengths incorrectly:
- Off-by-one mistakes
- Null terminator miscalculations
- Integer truncation/overflow
Legacy Native Code
Large C/C++ codebases continue to expose stack memory directly.
Assumption That Mitigations “Solve It”
Compiler protections reduce exploitability but do not eliminate the bug.
Modern Exploitation Techniques
Return Address Overwrite
Classic redirection of instruction pointer after function return.
ROP (Return-Oriented Programming)
Chain existing instruction sequences to bypass NX/DEP.
Stack Pivoting
Move stack pointer to attacker-controlled memory.
Partial Return Address Overwrite
Modify only low bytes for precision bypasses.
Data-Only Corruption
Corrupt stack-resident flags/variables without full control-flow hijack.
Visual: Stack Overflow Exploitation Chain
How CWE-121 Differs from CWE-120
Developers often confuse these related CWEs.
CWE-120
Broadly covers:
Buffer copy without checking input size.
CWE-121
Specifically covers:
Stack-allocated buffer overflow.
CWE-121 is a more specific subtype focused on stack memory.
Secure Coding Examples
Unsafe
strcpy(buf, input);
Safer
snprintf(buf, sizeof(buf), "%s", input);
Better
std::string safe = input;
Prefer abstractions that manage memory automatically.
Framework / Language Mitigations
Compiler Protections
Use:
- Stack canaries (
-fstack-protector) - ASLR
- NX/DEP
- Shadow stacks / CET
- CFI
Sanitizers
Run during testing:
- AddressSanitizer
- UBSan
Memory-Safe Languages
Prefer when practical:
- Rust
- Go
- Java
- C#
Defense in Depth
Ban Unsafe Stack Copy Patterns
Disallow dangerous functions in coding standards.
Validate Lengths Before Copying
Always prove data fits destination.
Fuzz Boundary Conditions
Boundary bugs frequently surface quickly under fuzzing.
Harden High-Risk Native Components
Parsers and protocol handlers deserve special scrutiny.
Final Thoughts
Stack-based buffer overflows remain foundational to exploit development because they target one of the most security-sensitive memory regions in a process: the call stack.
They persist because:
- Native code remains widespread
- Unsafe APIs survive in legacy systems
- Boundary logic is easy to get wrong
- Mitigations reduce but do not remove risk
The core lesson is simple:
If untrusted input can overwrite the stack, attackers may control what your program does when the function returns.
Modern mitigations make exploitation harder, but secure software still begins with correct bounds handling.

3 thoughts on “CWE-121: Stack-Based Buffer Overflow — When Input Overwrites the Call Stack”