A buffer overflow vulnerability occurs when a program writes more data into a fixed-size block of memory than that block was allocated to hold, letting the excess bytes spill into adjacent memory and overwrite things the program never intended to change — return addresses, function pointers, adjacent variables, or heap metadata. The bug class dates back to at least 1988, when the Morris Worm exploited an unbounded gets() call in the Unix fingerd daemon to become the first self-propagating internet worm. Nearly four decades later, buffer overflows still land in the top five of MITRE's CWE Top 25 Most Dangerous Software Weaknesses every year, and they remain a reliable path to remote code execution because C and C++ — the languages most exposed to this class — still run the kernels, hypervisors, browsers, and network stacks that everything else depends on. Understanding exactly how the overwrite happens is the first step to catching it before an attacker does.
What is a buffer overflow vulnerability?
A buffer overflow vulnerability is a memory-safety flaw where a program copies data into a buffer without checking that the data fits, so bytes beyond the buffer's boundary overwrite neighboring memory. The classic example is C's strcpy(dest, src), which copies until it hits a null terminator in src with no regard for how large dest actually is. If dest is a 64-byte stack buffer and src contains 200 attacker-controlled bytes, the extra 136 bytes land wherever the stack layout puts them next — often the saved return address of the current function. CWE-121 (stack-based) and CWE-122 (heap-based) are the two formal classifications MITRE uses, and both have appeared in the CWE Top 25 list every single year since the list's 2019 inception, most recently ranking #7 overall in the 2023 edition with over 3,000 associated CVEs.
How does a buffer overflow actually corrupt memory?
A buffer overflow corrupts memory by writing past the end of an allocated region and overwriting whatever the memory allocator or compiler placed immediately after it. On the stack, a function's local buffer typically sits below the saved frame pointer and return address; overflow it far enough and you overwrite the return address itself, so when the function executes ret, the CPU jumps to an attacker-chosen address instead of the caller. On the heap, overflowing a chunk allocated by malloc corrupts adjacent chunk metadata — size fields, free-list pointers — which heap exploitation techniques like "unlink" or "House of Force" attacks turn into arbitrary write primitives. This is why a single missing bounds check in, say, a JPEG parser or a DNS message decoder can escalate from "crash" to "attacker controls the instruction pointer": the corrupted data isn't just wrong, it's structurally load-bearing for how the program decides what to execute next.
What are the main types of buffer overflow attacks?
The main types are stack-based overflows, heap-based overflows, integer overflows that lead to buffer overflows, and off-by-one overflows, each targeting a different memory region or arithmetic edge case. Stack-based overflows (CWE-121) hijack return addresses or saved registers and are the oldest and most taught variant. Heap-based overflows (CWE-122) corrupt dynamically allocated memory and chunk metadata, and dominate modern browser and media-parser exploits because heap layouts are easier to groom predictably at scale. Integer overflow-to-buffer-overflow bugs occur when a size calculation like count * sizeof(item) wraps around a 32-bit boundary, producing a small or negative allocation size that a subsequent write then blows past — this pattern was central to CVE-2020-1350 ("SigRed"), a wormable Windows DNS Server flaw with a CVSS score of 10.0. Off-by-one overflows write exactly one byte too far, often via a loop boundary error (<= instead of <), and while a single byte sounds trivial, overwriting the low byte of a saved pointer is enough to redirect execution on many architectures.
Which real-world breaches and CVEs were caused by buffer overflows?
Buffer overflows have caused some of the most consequential security incidents in computing history, spanning from 1988 to the present day. The Morris Worm (1988) used a stack overflow in fingerd to infect an estimated 6,000 machines — roughly 10% of the internet at the time. EternalBlue (CVE-2017-0144), a buffer overflow in Microsoft's SMBv1 protocol, was weaponized in the May 2017 WannaCry ransomware outbreak that hit over 200,000 systems across 150 countries, including the UK's National Health Service. CVE-2021-3156 ("Baron Samedit"), a heap-based buffer overflow in sudo disclosed in January 2021, had sat unpatched in the codebase for roughly ten years and allowed any local user to gain root on nearly every major Linux distribution. More recently, CVE-2023-4863, a heap buffer overflow in the libwebp image library disclosed in September 2023, was exploited as part of the BLASTPASS zero-click chain used to deploy NSO Group's Pegasus spyware against iOS devices, and its downstream impact touched Chrome, Firefox, Electron, and hundreds of dependent applications because libwebp is bundled so widely.
How can developers prevent buffer overflow vulnerabilities?
Developers prevent buffer overflows primarily by eliminating unchecked memory operations at the language and compiler level, then backstopping what remains with exploit mitigations. Replacing unsafe C functions (strcpy, sprintf, gets) with bounds-checked equivalents (strncpy, snprintf, fgets) removes the most common footgun, and static analyzers like Coverity, CodeQL, or -Wformat-security flags catch a large share of these at build time. Compiler and OS mitigations — stack canaries, ASLR (address space layout randomization), DEP/NX (non-executable stack), and _FORTIFY_SOURCE — don't fix the bug but make successful exploitation dramatically harder, which is why modern exploits chase multi-stage bypasses instead of single-shot overflows. The more durable fix is migrating hot paths to memory-safe languages: Google reported in 2022 that Android's share of memory-safety vulnerabilities dropped from 76% of total vulnerabilities in 2019 to 35% in 2022 as new code shifted to Rust and Kotlin, and the U.S. government's 2024 ONCD report explicitly recommended memory-safe languages as a national cybersecurity priority.
How Safeguard Helps
Safeguard closes the gap between "a buffer overflow CVE exists in your dependency tree" and "this instance is actually exploitable in your running service." Griffin AI, Safeguard's reasoning engine, performs reachability analysis on native and interpreted call graphs to determine whether the vulnerable code path — the specific overflow-prone function — is ever invoked by your application, cutting through the noise of CVEs that technically apply but never execute. Safeguard generates and ingests SBOMs across your build pipeline to maintain a live inventory of every C/C++ library, static binary, and container base image where memory-unsafe code could hide, then continuously matches that inventory against new CVE disclosures like the CVE-2023-4863 libwebp case. When a fix is available, Safeguard opens an auto-fix pull request with the patched dependency version pinned and the reachability evidence attached, so security and engineering teams can triage by actual exploitability rather than CVSS score alone.