integer-overflow-anti-pattern
Integer Overflow Anti-Pattern
Severity: High
Summary
Integer overflow occurs when arithmetic operations exceed the maximum value for a data type, causing values to wrap around to small or negative numbers instead of erroring. Individually valid user-controlled inputs combined in calculations create exploitable conditions. Attackers bypass security checks, trigger buffer overflows, and manipulate financial transactions through overflow exploitation.
The Anti-Pattern
Never perform arithmetic operations on user-controlled inputs without checking for overflow. Individual input validation is insufficient.
BAD Code Example
// VULNERABLE: Individual values are checked, but their multiplication can overflow.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void process_purchase(uint32_t quantity, uint32_t price_per_item) {
// Both inputs are validated and seem reasonable on their own.
if (quantity > 1000) {
printf("Error: Quantity too high.\n");
return;
}
if (price_per_item > 100000) {
printf("Error: Price per item too high.\n");
return;
}
// Attacker sets `quantity = 50000` and `price_per_item = 100000`.
// Both might pass initial checks if those checks are weak.
// The expected total is 5,000,000,000.
// The maximum value for a 32-bit unsigned integer is 4,294,967,295.
uint32_t total_cost = quantity * price_per_item; // OVERFLOW!
// The `total_cost` wraps around to a small number (705,032,704 in this case).
// The attacker is charged a fraction of the real price.
printf("Charging customer: %u\n", total_cost);
charge_customer(total_cost);
}
GOOD Code Example
// SECURE: Check for potential overflow before performing the multiplication.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void process_purchase_safe(uint32_t quantity, uint32_t price_per_item) {
if (quantity > 1000) {
printf("Error: Quantity too high.\n");
return;
}
if (price_per_item > 100000) {
printf("Error: Price per item too high.\n");
return;
}
// Pre-condition check: before multiplying, verify if the result would exceed the maximum value.
if (price_per_item > 0 && quantity > UINT32_MAX / price_per_item) {
printf("Error: Potential overflow detected. Transaction cancelled.\n");
return;
}
// The multiplication is now safe to perform.
uint32_t total_cost = quantity * price_per_item;
printf("Charging customer: %u\n", total_cost);
charge_customer(total_cost);
}
Language-Specific Examples
Python:
# VULNERABLE: Python 3 has arbitrary precision integers, but C extensions don't
import ctypes
def allocate_buffer(width, height, bytes_per_pixel):
# Individually valid: width=1000000, height=1000000, bytes_per_pixel=4
# Product: 4,000,000,000,000 - may overflow in C extension
size = width * height * bytes_per_pixel
# When passed to C extension expecting int32:
buffer = ctypes.create_string_buffer(size) # Overflow in C layer!
return buffer
# SECURE: Check for overflow before calculation
import sys
def allocate_buffer_safe(width, height, bytes_per_pixel):
MAX_INT32 = 2**31 - 1
# Check multiplication won't overflow
if height > 0 and width > MAX_INT32 // (height * bytes_per_pixel):
raise ValueError("Buffer size would overflow")
size = width * height * bytes_per_pixel
if size > MAX_INT32:
raise ValueError(f"Buffer size {size} exceeds maximum")
buffer = ctypes.create_string_buffer(size)
return buffer
JavaScript:
// VULNERABLE: JavaScript numbers are 64-bit floats but lose precision
function calculateTotal(quantity, pricePerUnit) {
// Numbers > 2^53 lose precision
// quantity=10000000000000, pricePerUnit=100
const total = quantity * pricePerUnit; // Precision loss!
return total;
}
// SECURE: Use BigInt for large calculations
function calculateTotalSafe(quantity, pricePerUnit) {
const MAX_SAFE = Number.MAX_SAFE_INTEGER; // 2^53 - 1
// Check for overflow before calculating
if (quantity > MAX_SAFE / pricePerUnit) {
throw new Error('Calculation would overflow safe integer range');
}
const total = quantity * pricePerUnit;
return total;
}
// Or use BigInt for arbitrary precision
function calculateTotalBigInt(quantity, pricePerUnit) {
const total = BigInt(quantity) * BigInt(pricePerUnit);
return total;
}
Java:
// VULNERABLE: Multiplication without overflow check
public long calculateTotalPrice(int quantity, int pricePerItem) {
// Both int32, but product may overflow before promotion to long
long total = quantity * pricePerItem; // Overflow before cast!
return total;
}
// SECURE: Use Math.multiplyExact or manual checks
public long calculateTotalPriceSafe(int quantity, int pricePerItem) {
try {
// Math.multiplyExact throws ArithmeticException on overflow
return Math.multiplyExact(quantity, pricePerItem);
} catch (ArithmeticException e) {
throw new IllegalArgumentException("Price calculation overflow", e);
}
}
// Alternative: Cast to long before multiplication
public long calculateTotalPriceSafe2(int quantity, int pricePerItem) {
long total = (long) quantity * pricePerItem;
if (total > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Total exceeds maximum");
}
return total;
}
Detection
- Audit arithmetic operations on user inputs: Search for multiplications and additions:
rg '\*|[+]' --type c --type cpp -A 2 -B 2(C/C++)rg 'quantity.*price|amount.*rate|size.*count' -i- Focus on financial calculations, memory allocations, buffer sizes
- Find missing overflow checks: Identify operations without pre-checks:
rg '(?<!if.*)\w+\s*[*+]\s*\w+' --type c- Look for calculations not preceded by validation
- Test boundary values: Fuzz with extreme values:
- INT32_MAX: 2,147,483,647
- UINT32_MAX: 4,294,967,295
- INT64_MAX: 9,223,372,036,854,775,807
- Use SAST tools: Automated overflow detection:
- CodeQL:
cpp/uncontrolled-arithmetic - Clang Static Analyzer:
-analyzer-checker=security.intoverflow - Semgrep rules for integer overflow patterns
- CodeQL:
Prevention
- Check before you calculate: Before performing an arithmetic operation, check if it will result in an overflow. For multiplication (
a * b), the check isif (a > MAX_INT / b). For addition (a + b), it'sif (a > MAX_INT - b). - Use a larger data type: If you expect large numbers, use a 64-bit integer (
long longin C,longin Java) instead of a 32-bit one. - Use arbitrary-precision libraries: For financial calculations where precision is critical, use a library that handles numbers of arbitrary size (e.g.,
BigDecimalin Java,decimalin Python). - Use compiler-level protections: Some modern compilers provide flags (like
-ftrapvin GCC/Clang) that can detect and abort on signed integer overflows.
Related Security Patterns & Anti-Patterns
- Missing Input Validation Anti-Pattern: While input validation is necessary, it is not sufficient on its own to prevent integer overflows.
- Type Confusion Anti-Pattern: Incorrect assumptions about data types can lead to a variety of numeric vulnerabilities, including overflows.
References
More from igbuend/grimbard
tikz
LaTeX TikZ/PGF package for programmatic vector graphics and diagrams. Use when helping users draw flowcharts, trees, graphs, automata, circuits, geometric figures, or any custom diagram in LaTeX.
91latex
Comprehensive LaTeX reference for document creation, formatting, mathematics, tables, figures, bibliographies, and compilation. Use when helping users write, edit, debug, or compile LaTeX documents.
38pgfplots
LaTeX pgfplots package for data visualization and plotting. Use when helping users create line plots, bar charts, scatter plots, histograms, 3D surfaces, or any scientific/data plot in LaTeX.
31biblatex
LaTeX biblatex/biber packages for modern bibliography management. Use when helping users cite references, manage .bib files, choose citation styles, or troubleshoot bibliography compilation.
24ethical-hacking-ethics
Legal and ethical guidelines for bug bounties, pentesting, and security research. Use when conducting authorized security testing.
12amsmath
LaTeX amsmath/amssymb/mathtools packages for mathematical typesetting. Use when helping users write equations, align math, use mathematical symbols, matrices, theorems, or any advanced math formatting.
12