Wrap-around Error

Description

Wrap-around Error occurs when an integer value is incremented beyond its maximum representable value, causing it to "wrap around" to its minimum value (often zero or a large negative number). In unsigned integers, incrementing past the maximum wraps to zero. In signed integers, overflow behavior is undefined in C/C++ but typically wraps to the minimum negative value. Wrap-around errors are particularly dangerous when the affected integer is used for security-critical calculations such as buffer sizes, array indices, or loop counters, potentially leading to buffer overflows, infinite loops, or other memory corruption.

Risk

Wrap-around errors are highly exploitable because they can transform large values into small or negative values, bypassing security checks. A classic attack involves providing a large size value that wraps to a small allocation size, followed by operations that assume the original large size—resulting in massive buffer overflows. Wrap-around in loop counters can cause infinite loops or premature termination. These vulnerabilities have enabled remote code execution in countless applications, particularly those handling network protocols, file formats, or user-supplied size parameters.

Solution

Always validate integer values before arithmetic operations that could cause wrap-around. Use safe integer arithmetic libraries that detect overflow (SafeInt in C++, checked arithmetic in Rust). Check for maximum values before incrementing. Use larger integer types when possible (64-bit instead of 32-bit). Implement explicit overflow checks before size calculations used in memory allocation. Consider compiler flags that trap on overflow (-ftrapv in GCC). Avoid unsigned integers for values that will be subtracted, as underflow wraps to large positive values.

Common Consequences

ImpactDetails
IntegrityScope: Memory Corruption

Wrap-around in size calculations leads to undersized buffer allocations and subsequent overflows when the original value is used.
AvailabilityScope: Denial of Service

Wrap-around in loop counters causes infinite loops; wrap-around in array indices causes crashes.
Access ControlScope: Code Execution

Buffer overflows resulting from wrap-around errors can enable arbitrary code execution.

Example Code + Solution Code

Vulnerable Code

#include <stdlib.h>
#include <string.h>

// VULNERABLE: Integer wrap-around in size calculation
void allocate_table(unsigned int num_entries) {
    // If num_entries is large, multiplication wraps around
    size_t size = num_entries * sizeof(int);  // Wraps to small value

    int *table = malloc(size);  // Allocates tiny buffer

    // Later code treats table as having num_entries elements
    for (unsigned int i = 0; i < num_entries; i++) {
        table[i] = 0;  // Massive buffer overflow
    }
}

// VULNERABLE: Increment wrap-around
void process_loop(unsigned char count) {
    unsigned char i = 0;
    // If count is 255 and incremented, wraps to 0
    while (i <= count) {
        process_item(i);
        i++;  // When i=255, i++ wraps to 0, loop never ends
    }
}

// VULNERABLE: Addition overflow in bounds check
int safe_add_wrong(int a, int b, int *result) {
    // This check is insufficient - overflow happens before comparison
    if (a + b < a) {  // Undefined behavior in signed overflow
        return -1;
    }
    *result = a + b;
    return 0;
}

Fixed Code

#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>

// SAFE: Check for overflow before multiplication
void *allocate_table_safe(size_t num_entries) {
    // Check for multiplication overflow
    if (num_entries > SIZE_MAX / sizeof(int)) {
        return NULL;  // Would overflow
    }

    size_t size = num_entries * sizeof(int);
    int *table = malloc(size);

    if (table) {
        memset(table, 0, size);  // Use calculated size
    }
    return table;
}

// SAFE: Avoid wrap-around in loop
void process_loop_safe(unsigned int count) {
    for (unsigned int i = 0; i < count; i++) {
        process_item(i);
    }
    // Handle the last item separately if needed
    if (count > 0) {
        process_item(count);
    }
}

// SAFE: Check for overflow before arithmetic
int safe_add(int a, int b, int *result) {
    // Check before performing addition
    if (b > 0 && a > INT_MAX - b) {
        return -1;  // Would overflow
    }
    if (b < 0 && a < INT_MIN - b) {
        return -1;  // Would underflow
    }
    *result = a + b;
    return 0;
}

// SAFE: Use size_t for sizes and check overflow
size_t safe_multiply(size_t a, size_t b) {
    if (a != 0 && b > SIZE_MAX / a) {
        return 0;  // Overflow, return error indicator
    }
    return a * b;
}

Exploited in the Wild

OpenSSH Challenge-Response (OpenSSH, 2002)

CVE-2002-0639 was an integer overflow in OpenSSH's challenge-response authentication that allowed remote attackers to execute arbitrary code by exploiting wrap-around in a size calculation.

Windows Image Processing (Microsoft, Multiple)

Multiple integer overflow vulnerabilities in Windows GDI+ and image processing libraries have been exploited through malicious image files with crafted dimension values that cause wrap-around.

PNG Library Integer Overflow (libpng, 2015)

CVE-2015-8126 was an integer overflow in libpng that could lead to heap buffer overflows when processing PNG images with maliciously crafted chunk sizes.


Tools to test/exploit

  • UBSan — undefined behavior sanitizer that detects signed integer overflow.

  • SafeInt — C++ library for safe integer arithmetic with overflow detection.

  • AFL++ — fuzzer effective at discovering integer overflow conditions.


CVE Examples

  • CVE-2002-0639 — OpenSSH integer overflow in challenge-response authentication.

  • CVE-2015-8126 — libpng integer overflow leading to buffer overflow.

  • CVE-2021-21300 — Git integer overflow enabling RCE on case-insensitive filesystems.


References

  1. MITRE. "CWE-128: Wrap-around Error." https://cwe.mitre.org/data/definitions/128.html

  2. CERT. "INT30-C. Ensure that unsigned integer operations do not wrap." https://wiki.sei.cmu.edu/confluence/display/c/INT30-C