Loading learning content...
On February 25, 1991, during the Gulf War, a Patriot missile defense system in Dhahran, Saudi Arabia failed to intercept an incoming Iraqi Scud missile. The Scud struck an American Army barracks, killing 28 soldiers and injuring around 100 others.
The cause? A cumulative rounding error in time calculation. The Patriot system tracked time as the number of tenths of a second since boot. This was stored using 24-bit integer arithmetic. After running continuously for about 100 hours, the accumulated error in the time calculation was 0.34 seconds. In that time, a Scud missile traveling at Mach 5 moves over half a kilometer—far enough that the Patriot's range gate couldn't detect it.
This wasn't a design flaw in the abstract—it was an integer precision bug with lethal consequences.
Throughout computing history, integer-related bugs have caused rockets to explode, billions of dollars in losses, security breaches affecting millions, and deaths. These aren't rare events. They're systematic consequences of ignoring what you're learning in this module.
By the end of this page, you will understand: (1) Multiple real-world catastrophes caused by integer bugs, (2) The patterns that lead to these failures, (3) How to systematically avoid integer-related bugs in your own code, and (4) Defense-in-depth strategies for safety-critical systems.
The Ariane 5 explosion is perhaps the most famous integer overflow disaster in computing history. It cost hundreds of millions of dollars and set the European space program back years.
The mission:
On June 4, 1996, the maiden flight of Ariane 5, Europe's newest and most powerful launch vehicle, carried four Cluster satellites worth about $500 million. The rocket launched successfully from French Guiana.
The failure:
At T+37 seconds, the rocket suddenly veered off course, broke apart due to aerodynamic forces, and self-destructed. The debris rained down over the Guiana jungle and ocean.
The root cause:
The Inertial Reference System (IRS) contained code reused from the Ariane 4. This code converted a 64-bit floating-point value (horizontal velocity) to a 16-bit signed integer. On Ariane 4, this worked fine because that rocket's trajectory never produced velocities that exceeded the 16-bit range.
Ariane 5 was more powerful. Its horizontal velocity exceeded 32,767 (the maximum 16-bit signed value). The conversion overflowed, producing garbage data. The guidance computer interpreted this as a massive attitude error and commanded maximum thruster deflection to "correct" it. The rocket tore itself apart.
| Sequence | Event | Technical Cause |
|---|---|---|
| T+0 | Launch | Normal |
| T+30s | Velocity exceeds Ariane 4 limits | More powerful engines |
| T+36.7s | 64-bit float → 16-bit int conversion | Operand error (overflow) |
| T+36.7s | Primary IRS shuts down | Hardware protection triggered |
| T+36.7s | Backup IRS sends garbage data | Same bug—no redundancy |
| T+37s | Guidance issues max nozzle deflection | Interprets garbage as attitude error |
| T+39s | Aerodynamic breakup | Rocket can't survive 20° rotation |
| T+39s | Self-destruct triggered | Safety system activates |
What made this worse:
Code reuse without analysis: The IRS code from Ariane 4 was reused in Ariane 5 without verifying that all assumptions still held.
No runtime protection: The conversion lacked bounds checking. A simple if (value > INT16_MAX) could have detected the problem.
Redundancy failure: The backup IRS ran identical software, so both failed simultaneously.
The code wasn't even needed: The problematic conversion occurred in alignment software that was only needed before liftoff. It continued running past launch due to a design decision for Ariane 4 that was never reconsidered for Ariane 5.
After years of analysis and hundreds of millions of euros, the official investigation concluded that the root cause was a software exception caused by converting a 64-bit float to a 16-bit integer when the float contained a value outside the 16-bit range. A bug a first-year computer science student could explain destroyed a rocket program.
The Therac-25 incidents are among the most studied software disasters in history. They resulted in patient deaths and severe injuries from massive radiation overdoses during cancer treatment.
The system:
Therac-25 was a computer-controlled radiation therapy machine. It could deliver either low-energy electron beams directly or high-energy X-rays (generated by striking a metal target with high-energy electrons). The mode was selected by software.
The bugs:
Multiple software issues, including integer-related bugs, caused the machine to deliver radiation at wrong energies:
Race condition with counter overflow: A counter variable would overflow, and if the operator typed commands at a specific moment (faster than the system expected), a race condition would cause the machine to fire in high-energy mode without the beam-spreading equipment in place.
Flag as 1-byte counter: A critical safety flag was a 1-byte value that was incremented every time through a loop. When it was non-zero, certain safety checks were bypassed. After 256 iterations (one byte overflow), the flag would wrap to zero, enabling the safety checks—but only briefly before wrapping again.
The consequences:
At least six patients received massive radiation overdoses (100x the intended dose). Three died directly from radiation overexposure. Others suffered severe radiation injuries including limb amputation.
Therac-25 teaches that software must never be the sole safety barrier for systems that can harm humans. Integer overflow in a safety flag should have triggered fail-safe shutdown, not silently bypassed safety checks. Defense in depth—multiple independent safety mechanisms—is essential for critical systems.
In 2015, the Federal Aviation Administration (FAA) issued an emergency airworthiness directive for all Boeing 787 Dreamliner aircraft. The cause? Another integer overflow bug.
The bug:
The Boeing 787's generator control units (GCUs) used a counter to track time since power-up. This counter was stored as a signed 32-bit integer representing hundredths of a second.
The overflow:
$$2^{31} - 1 \text{ hundredths of a second} = 248.55 \text{ days}$$
After running continuously for approximately 248 days, the counter would overflow. When this happened, the GCU would shut down, potentially causing all four main generators to fail simultaneously and resulting in complete loss of electrical power to the aircraft.
The FAA directive:
"We are issuing this AD to prevent loss of all AC electrical power, which could result in loss of control of the airplane."
The immediate fix? Reboot the generators at least every 120 days. The permanent fix required a software update.
| System | Counter Width | Time to Overflow | Consequence |
|---|---|---|---|
| Boeing 787 GCU | 32-bit (1/100 sec) | 248 days | Generator shutdown |
| Boeing 787 (different subsystem) | 32-bit (1/100 sec) | 248 days | Multiple subsystem failures |
| Airbus A350 | Similar | Similar | Required similar fixes |
| F-22 Raptor (early) | Various | Variable | Computer resets when crossing date line |
Why this keeps happening:
Long operational periods: Aircraft, unlike desktop computers, may run continuously for weeks or months without reboot.
Legacy assumptions: Code written assuming short operating periods gets reused in long-duration systems.
Counter width mis-selection: 32-bit counters seem "big enough" until you do the math.
Testing limitations: Running a system for 248 days under test conditions is impractical.
The fix pattern:
For time counters in critical systems:
Before choosing a counter width, always calculate: "How long until this overflows?" For a 32-bit counter incrementing every millisecond: 2^31 ms ≈ 24.8 days. For 32-bit @ microseconds: about 35 minutes. For 64-bit @ nanoseconds: over 292 years. Choose accordingly.
Integer overflow bugs aren't limited to life-critical systems. They've caused chaos in gaming, finance, and everyday software.
Civilization "Gandhi the Nuclear Warmonger" Bug:
In the original Civilization game (1991), each leader had an "aggression" rating from 1-12. Gandhi, the peaceful leader, started with an aggression of 1. When players adopted democracy, all leaders' aggression decreased by 2.
The problem: aggression was stored as an unsigned byte. Gandhi's aggression going from 1 to 1-2 = -1 wrapped around to 255—the maximum possible aggression. Gandhi became a nuclear-armed psychopath.
(Note: Sid Meier has stated this may be partly legend, but the bug type is real and instructive.)
World of Warcraft "Corrupted Blood" Economy:
While not strictly overflow, WoW has had multiple integer bugs:
Financial System Bugs:
Knight Capital Group (2012):
Not purely an integer bug, but a software deployment error caused Knight's trading algorithms to execute millions of erroneous trades in 45 minutes, resulting in a $440 million loss. Integer checks and limits, if properly implemented, could have prevented the cascading failure.
Penny Stock Overflow:
Trading systems processing stock prices in integer cents have experienced bugs when:
Bitcoin Integer Overflow (2010):
In August 2010, a bug in Bitcoin allowed creation of 184 billion BTC through an integer overflow. The transaction created outputs totaling more than the 21 million BTC cap.
Value: 4,296,967,296 satoshis (overflowed from negative)
Should have been: -4,296,967,296 (negative, invalid)
The bug was caught within hours and the blockchain forked to reject the transaction.
Financial calculations require extreme care with integer representation. Using floating-point for money leads to rounding errors. Using integers requires careful handling of decimal precision and overflow. Many systems use arbitrary-precision decimals or scaled integers (cents, not dollars) with rigorous overflow checking.
Integer overflow is a major category of security vulnerability. The CWE (Common Weakness Enumeration) and CVE (Common Vulnerabilities and Exposures) databases contain thousands of entries related to integer issues.
CWE-190: Integer Overflow or Wraparound
This weakness occurs when a calculation produces an integer that is outside the range of the type used to store it. Common exploitation patterns include:
malloc(count * size) overflows, allocating a tiny buffer, then filled with attacker-controlled data12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
#include <stdlib.h>#include <string.h> // CVE-2002-0639: OpenSSH Challenge-Response Integer Overflow// Simplified reconstruction of the vulnerability pattern // VULNERABLE: Integer overflow in input validationint process_challenges_vulnerable(int num_challenges, void* data) { // Attacker sends num_challenges = 0x40000000 // sizeof(challenge_t) = 16 bytes // 0x40000000 * 16 = 0x400000000, but truncated to 32-bit = 0 size_t total_size = num_challenges * sizeof(challenge_t); challenge_t* challenges = malloc(total_size); // Allocates 0 or tiny buffer! if (!challenges) return -1; // Copies num_challenges * 16 bytes into a too-small buffer memcpy(challenges, data, num_challenges * sizeof(challenge_t)); // OVERFLOW! // ... process challenges ... free(challenges); return 0;} // SECURE: Check for overflow before allocationint process_challenges_secure(int num_challenges, void* data) { // Validate num_challenges is non-negative if (num_challenges < 0) return -1; // Check multiplication won't overflow if (num_challenges > SIZE_MAX / sizeof(challenge_t)) { return -1; // Would overflow } size_t total_size = (size_t)num_challenges * sizeof(challenge_t); // Additional sanity check: reasonable maximum if (total_size > MAX_REASONABLE_SIZE) { return -1; } challenge_t* challenges = malloc(total_size); if (!challenges) return -1; memcpy(challenges, data, total_size); // ... process challenges ... free(challenges); return 0;}Notable Integer Overflow CVEs:
| CVE | Software | Impact |
|---|---|---|
| CVE-2002-0639 | OpenSSH | Remote root compromise |
| CVE-2004-0200 | Windows GDI+ (JPEG) | Remote code execution via image |
| CVE-2006-3459 | Libtiff | Multiple overflow vulnerabilities |
| CVE-2010-2753 | Firefox | Remote code execution via integer overflow |
| CVE-2014-1776 | Internet Explorer | Remote code execution (used in attacks) |
| CVE-2015-1538 | Android Stagefright | Remote code execution via video |
The pattern is consistent: trusted size calculations overflow, leading to undersized allocations, which are then overwritten with attacker-controlled data, enabling code execution.
MITRE rates integer overflow vulnerabilities as highly severe. They consistently appear in OWASP, SANS, and CWE top vulnerability lists. Every security-conscious developer must understand and actively defend against integer overflow.
After examining these disasters, clear patterns emerge. Understanding these patterns—and their defenses—is essential for writing robust software.
malloc(n * sizeof(x))for(i=0; i < user_count; i++)(size_t)a * b-ftrapv, sanitizerssafe_add(), safe_mult()Defense in Depth: Multiple Layers
Language/Compiler Level:
-Wall -Wextra -Wconversion-fsanitize=undefined,integerCode Level:
Testing Level:
Architecture Level:
In safety engineering, the Swiss Cheese Model describes how accidents occur when holes in multiple defense layers align. Each layer (language, compiler, code review, testing, architecture) has holes. By having multiple independent layers, you reduce the chance of a bug slipping through. No single defense is sufficient alone.
Programming language designers have learned from decades of integer bugs. Newer languages incorporate safety mechanisms by default.
| Language | Default Behavior | Safe Alternatives | Notes |
|---|---|---|---|
| Rust | Panic in debug, wrap in release | checked_, saturating_, wrapping_* | Explicit overflow handling |
| Swift | Trap (crash) | &+ &- &* for wrap | Overflow is always an error unless explicitly allowed |
| Go | Wrap silently | Manual checks required | Similar to C, but no undefined behavior |
| Java | Wrap silently | Math.addExact() throws | Safe methods added in Java 8 |
| C# (.NET) | Wrap by default | checked { } keyword | Opt-in overflow checking blocks |
| Python | Unlimited precision | N/A | Can't overflow, but can exhaust memory |
| JavaScript | 64-bit float | BigInt for large integers | Loses precision beyond 2^53 |
123456789101112131415161718192021222324252627282930313233343536373839404142434445
// Rust: Explicit overflow handling fn main() { let a: u8 = 250; let b: u8 = 10; // DEFAULT: Panics in debug mode, wraps in release // let c = a + b; // Would panic in debug! // CHECKED: Returns None on overflow match a.checked_add(b) { Some(result) => println!("Checked: {}", result), None => println!("Overflow detected!"), } // SATURATING: Clamps to max/min value let c = a.saturating_add(b); // c = 255 (max u8) println!("Saturating: {}", c); // WRAPPING: Explicit wraparound let d = a.wrapping_add(b); // d = 4 (250 + 10 - 256) println!("Wrapping: {}", d); // OVERFLOWING: Returns (result, overflow_flag) let (result, overflowed) = a.overflowing_add(b); println!("Overflowing: {} (overflow: {})", result, overflowed);} // Swift: Overflow is always an error by defaultfunc swiftExample() { let a: UInt8 = 250 let b: UInt8 = 10 // let c = a + b // COMPILE ERROR: Would overflow at runtime // Use &+ for explicit wraparound let d = a &+ b // d = 4 // Or check before adding if a <= UInt8.max - b { let safe = a + b } else { print("Would overflow!") }}Rust's approach is exemplary: the default (panic in debug) catches bugs during development, while release mode wraps for performance. But more importantly, Rust provides four explicit methods for each arithmetic operation, forcing developers to consciously choose the handling strategy. This "make illegal states unrepresentable" philosophy prevents entire categories of bugs.
Use this checklist when writing or reviewing code that involves integer arithmetic:
malloc(n * size) calls protected against overflow?Per-language recommendations:
C/C++:
<stdint.h> / <cstdint> for fixed-width types-Wall -Wextra -Wconversion -Wsign-conversion-fsanitize=undefined,integerJava:
Math.addExact(), Math.multiplyExact() for safety-critical calculationsPython:
numpy fixed-width types when matching C dataJavaScript:
BigInt for integers beyond 2^53The best defense against integer bugs is internalizing range-awareness as a habit. Every time you write arithmetic, a small part of your mind should whisper: "What if these values are huge? What if they're negative? What if the result doesn't fit?" This automatic vigilance is the mark of a seasoned engineer.
Integer bugs have caused some of the most expensive and deadly software failures in history. Understanding and preventing them is essential for any serious software engineer.
Module Conclusion:
You've completed the Integer Data Types module. You now understand:
This knowledge is foundational. Every data structure, every algorithm, every piece of software you write involves integers. By understanding them deeply, you've built a foundation that will support everything else you learn in your programming career.
Congratulations! You've mastered Integer Data Types—from binary representation to catastrophic bugs. You now have the deep understanding necessary to write robust, efficient code that handles integers correctly. This foundational knowledge will inform everything you build as a software engineer.