Integer Data Types
Integer Overflow and Real-World Bugs
Read aloud is unavailable in this browser.
When Integer Overflow Becomes Catastrophe
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.
Case Study: Ariane 5 Explosion (1996)
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.
Case Study: Therac-25 Radiation Overdoses (1985-1987)
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.
- •Overconfidence in software: "Software can't fail like hardware"—but it fails differently and often more catastrophically
- •Removed hardware interlocks: Previous Therac versions had hardware safety mechanisms. Therac-25 replaced them with software-only protection.
- •Integer overflow in safety-critical code: Using a byte counter that could overflow meant safety checks were periodically disabled
- •Untested race conditions: The timing-dependent bugs only manifested with experienced, fast operators
- •Poor error messages: The machine displayed errors like "MALFUNCTION 54" with no explanation, leading operators to retry
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.
Case Study: Boeing 787 Power Shutdown (2015)
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:
- Use 64-bit integers (overflow after billions of years at microsecond resolution)
- Implement counter reset logic when appropriate
- Test edge cases with accelerated time simulation
- Have multiple independent time sources
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.
Case Study: Gaming and Financial Integer Bugs
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:
- Gold duplication exploits via overflow in transaction systems
- Item stat overflows creating impossibly powerful equipment
- Timestamp bugs causing events to trigger incorrectly
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:
- Stock splits create fractional cents
- High-precision calculations exceed integer limits
- Accumulated values overflow storage
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 Bugs as Security Vulnerabilities
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:
- •Heap overflow via allocation:
malloc(count * size)overflows, allocating a tiny buffer, then filled with attacker-controlled data - •Array index out of bounds: Size checks pass due to overflow, but subsequent access reads/writes beyond allocated memory
- •Bypass of security checks: Comparisons produce incorrect results due to signedness issues
- •Denial of service: Overflow causes crash or infinite loop
- •Logic errors: Business logic fails when calculations produce unexpected values
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
#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.
Common Patterns and Prevention Strategies
After examining these disasters, clear patterns emerge. Understanding these patterns—and their defenses—is essential for writing robust software.
- •Unchecked size calculations:
malloc(n * sizeof(x)) - •Type narrowing: 64-bit → 32-bit or 32-bit → 16-bit
- •Signed/unsigned mixing: Comparisons, casts
- •User-controlled arithmetic: Calculations with untrusted input
- •Uptime counters: Time since boot in limited-width integers
- •Loop bound calculations:
for(i=0; i < user_count; i++) - •Pointer arithmetic: Adding offsets to pointers without validation
- •Pre-operation overflow checks: Validate before arithmetic
- •Use wider types for calculations:
(size_t)a * b - •Compiler overflow detection:
-ftrapv, sanitizers - •Safe integer libraries:
safe_add(),safe_mult() - •Language-level protection: Rust, Swift, modern C++ features
- •Input validation: Reject unreasonable values early
- •Code review focus areas: Allocations, casts, loops
Defense in Depth: Multiple Layers
-
Language/Compiler Level:
- Use languages with built-in overflow protection (Rust, Swift)
- Enable compiler warnings:
-Wall -Wextra -Wconversion - Use sanitizers during development:
-fsanitize=undefined,integer
-
Code Level:
- Use safe arithmetic functions with overflow detection
- Validate all external inputs before using in calculations
- Document and check invariants
-
Testing Level:
- Include boundary value testing (0, 1, MAX-1, MAX, MAX+1)
- Fuzzing with large/negative/edge-case values
- Static analysis tools (Coverity, PVS-Studio, etc.)
-
Architecture Level:
- Don't rely solely on software for safety-critical checks
- Implement watchdogs and sanity monitors
- Design for fail-safe behavior
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.
How Modern Languages Address Integer Safety
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.
KEEP LEARNING
There’s more to understand.
You’re reading the introduction. Create a free account to read the complete lesson, save notes and keep track of your progress.