Safeguard
Vulnerability Analysis

What is a Buffer Overflow

Buffer overflows have powered exploits from the 1988 Morris Worm to WannaCry. Here's how they work, why they persist, and how to stop them.

Shadab Khan
Security Engineer
6 min read

A buffer overflow happens when a program writes more data into a fixed-size block of memory than that block was allocated to hold, causing the excess bytes to spill into adjacent memory. That adjacent memory might store a return address, a function pointer, or another variable — and overwriting it can crash the program, corrupt data, or hand an attacker control of execution flow. Buffer overflows have been exploited for decades, starting with the 1988 Morris Worm's abuse of a gets() call in fingerd, and they remain dangerous today: CWE-787 ("Out-of-bounds Write") ranked #1 on MITRE's 2023 CWE Top 25 Most Dangerous Software Weaknesses, and CWE-119 ("Improper Restriction of Operations within the Bounds of a Memory Buffer") consistently sits in the top 10. Languages like C and C++, which manage memory manually and don't check array bounds by default, are the most common source. This glossary entry breaks down how buffer overflows work, why they're still common, and how to catch them before they ship.

What causes a buffer overflow?

A buffer overflow is caused by writing data past the boundary of an allocated buffer, usually because a program fails to validate input length before copying it into fixed-size memory. Classic culprits include unsafe C functions like strcpy(), gets(), sprintf(), and memcpy() when called with attacker-controlled length values instead of bounds-checked equivalents like strncpy() or snprintf(). Off-by-one errors in loop bounds, integer overflows that wrap a size calculation to a small or negative number, and missing length checks on network-supplied data are the three most frequent root causes seen in CVE writeups. Because C and C++ give developers direct pointer arithmetic and manual memory management without built-in bounds enforcement, roughly 70% of vulnerabilities that Microsoft assigned CVEs to over a multi-year period were memory-safety issues, according to Microsoft's own 2019 BlueHat analysis — and buffer overflows are the largest single category within that group.

How do attackers exploit a buffer overflow?

Attackers exploit a buffer overflow by overwriting adjacent memory with crafted data that redirects program execution to code they control. On the stack, a classic technique overwrites the saved return address on the call stack so that when the current function returns, execution jumps to attacker-supplied shellcode or to existing code via return-oriented programming (ROP). On the heap, attackers corrupt metadata (like malloc chunk headers) or overwrite adjacent objects — such as function pointers or vtable pointers — to hijack control flow indirectly. Modern exploits usually have to chain a buffer overflow with a second bug or bypass technique because mitigations like stack canaries, Address Space Layout Randomization (ASLR), and Data Execution Prevention (DEP/NX) block the simplest "jump straight to injected shellcode" approach. This is exactly what happened with EternalBlue (CVE-2017-0144), a buffer overflow in Microsoft's SMBv1 protocol that the WannaCry ransomware used in May 2017 to infect more than 200,000 systems across 150 countries in a matter of days.

What's the difference between a stack overflow and a heap overflow?

The difference between a stack overflow and a heap overflow is the memory region affected and what an attacker can corrupt as a result. Stack-based overflows occur in the call stack — the region storing local variables, saved registers, and return addresses — and are the more classic and generally easier-to-exploit variant because overwriting the return address gives fairly direct control of execution. Heap-based overflows occur in dynamically allocated memory (via malloc, new, etc.) and typically require corrupting heap metadata or an adjacent object to achieve code execution, which is harder but still very much exploitable in practice. Baron Samedit (CVE-2021-3156), disclosed in January 2021, is a heap-based buffer overflow in sudo versions 1.8.2 through 1.8.31p2 and 1.9.0 through 1.9.5p1 that let any local user gain root privileges without authentication — it had gone unnoticed in the codebase for nearly 10 years before Qualys researchers found it.

Are buffer overflows still common in modern software?

Yes, buffer overflows are still common, even though memory-safe languages have reduced their prevalence in new code. CISA and the FBI's 2023 joint advisory on secure-by-design software specifically called out memory-safety defects, including buffer overflows, as "a class of vulnerability that has plagued the software industry since the 1990s" and urged vendors to eliminate them at the design stage rather than patch them after the fact. Stagefright (CVE-2015-1538), a buffer overflow in Android's libstagefright media library disclosed in July 2015, affected an estimated 950 million Android devices and could be triggered by nothing more than receiving a malicious MMS message — no user interaction required. More recently, curl maintainers disclosed CVE-2023-38545, a heap buffer overflow in curl's SOCKS5 proxy handshake code (affecting versions 7.69.0 through 8.3.0), in October 2023, showing that even mature, heavily audited C codebases still ship overflow bugs. Legacy C/C++ code, embedded firmware, and network-facing parsers remain the highest-risk territory.

How can buffer overflows be prevented?

Buffer overflows can be prevented primarily by eliminating unchecked, fixed-size memory operations and by adopting compiler and OS-level protections that limit exploitability when a bug does slip through. Practical measures include: using bounds-checked functions (strncpy, snprintf, strlcpy) instead of their unsafe counterparts; enabling compiler mitigations such as stack canaries (-fstack-protector), ASLR, and DEP/NX, which are on by default in most modern compilers and OSes; running static analysis and fuzzers (like AFL++ or libFuzzer) against C/C++ code paths that parse untrusted input; and, where feasible, rewriting high-risk parsing or network-facing components in a memory-safe language like Rust or Go. The U.S. government's 2024 "Back to the Building Blocks" report from the Office of the National Cyber Director explicitly recommended migrating away from memory-unsafe languages for exactly this reason — buffer overflows are largely a solved problem in languages with automatic bounds checking.

How Safeguard Helps

Safeguard helps security teams find and fix buffer-overflow-class vulnerabilities before they reach production. Reachability analysis traces whether a vulnerable function — a strcpy() call in a transitive C dependency, for example — is actually invoked by code paths your application executes, cutting through noisy CVE feeds that flag every buffer-overflow CVE in your SBOM regardless of exploitability. Griffin AI, Safeguard's detection engine, analyzes code changes and dependency updates to flag risky memory-handling patterns and newly disclosed CWE-787/CWE-119 findings as they land, not weeks later in a batch scan. Safeguard's SBOM generation and ingest pipeline gives teams a continuously updated inventory of every C/C++ library in use, so a disclosure like a new sudo or curl CVE can be matched against your actual footprint within minutes. When a fix is available, Safeguard opens auto-fix pull requests that bump the vulnerable dependency to a patched version, so remediation ships as fast as detection.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.