Integer Underflow (Wrap or Wraparound)
Description
Integer Underflow occurs when an arithmetic subtraction operation produces a result that is less than the minimum value that can be stored in the target integer type, causing the value to "wrap around" to a large positive number (for unsigned) or to the maximum positive value (for signed integers). For example, subtracting 1 from an unsigned zero produces the maximum unsigned value (e.g., 4294967295 for 32-bit). Integer underflows are particularly dangerous when the resulting large value is used for buffer allocation, loop counters, or array indices, often leading to buffer overflows or denial of service.
Risk
Integer underflow vulnerabilities can have severe security consequences. When an underflowed value is used as a buffer size, it results in massive allocations that cause memory exhaustion or subsequent buffer overflows. When used as an array index, the huge positive value leads to out-of-bounds access. Attackers exploit these vulnerabilities by providing input that causes subtraction to produce negative intermediate results in signed arithmetic, or by manipulating values to cause unsigned arithmetic to underflow. This vulnerability class affects DNS servers, network protocols, and any code performing size calculations with subtraction.
Solution
Validate that subtraction operations will not underflow before performing them. Check that the minuend is greater than or equal to the subtrahend before unsigned subtraction. Use safe arithmetic functions that detect underflow conditions. Avoid mixing signed and unsigned integers in calculations. When casting between types, validate that values are within valid ranges. Enable compiler sanitizers (-fsanitize=unsigned-integer-overflow) during development. Use size_t for size-related calculations and check bounds before operations.
Common Consequences
| Impact | Details |
|---|---|
| Availability | Scope: Denial of Service Underflow producing massive allocation requests causes memory exhaustion and crashes. |
| Integrity | Scope: Memory Corruption Underflowed sizes or indices lead to buffer overflows and memory corruption. |
| Access Control | Scope: Code Execution Buffer overflows resulting from underflow enable arbitrary code execution. |
Example Code + Solution Code
Vulnerable Code
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
// VULNERABLE: Unsigned underflow
void process_data(uint32_t length, uint32_t header_size) {
// If header_size > length, this underflows to huge value
uint32_t data_size = length - header_size;
char *buffer = malloc(data_size); // Massive allocation or tiny on wrap
// ...
}
// VULNERABLE: Length underflow in protocol parsing
void parse_packet(const char *packet, size_t packet_len, size_t header_len) {
// Underflow if header_len > packet_len
size_t payload_len = packet_len - header_len;
// payload_len is now huge positive value
char *payload = malloc(payload_len); // Memory exhaustion
memcpy(payload, packet + header_len, payload_len); // Over-read
}
// VULNERABLE: Signed to unsigned cast after underflow
void copy_data(int len) {
int actual_len = len - HEADER_SIZE;
// If actual_len is negative, cast to size_t makes it huge
char *buf = malloc((size_t)actual_len);
read_data(buf, actual_len); // Disaster
}
Fixed Code
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
// SAFE: Check for underflow before subtraction
bool process_data_safe(uint32_t length, uint32_t header_size, char **out_buffer) {
// Validate: can we subtract without underflow?
if (header_size > length) {
return false; // Would underflow
}
uint32_t data_size = length - header_size;
// Additional sanity check
if (data_size > MAX_DATA_SIZE) {
return false;
}
*out_buffer = malloc(data_size);
return (*out_buffer != NULL);
}
// SAFE: Validate lengths before subtraction
int parse_packet_safe(const char *packet, size_t packet_len,
size_t header_len, char **payload, size_t *payload_len) {
// Check for underflow
if (header_len > packet_len) {
return -1; // Invalid: header larger than packet
}
*payload_len = packet_len - header_len;
// Check reasonable bounds
if (*payload_len > MAX_PAYLOAD_SIZE) {
return -1;
}
*payload = malloc(*payload_len);
if (!*payload) {
return -1;
}
memcpy(*payload, packet + header_len, *payload_len);
return 0;
}
// SAFE: Validate signed value before cast
bool copy_data_safe(int len) {
if (len < HEADER_SIZE) {
return false; // Not enough data for header
}
int actual_len = len - HEADER_SIZE;
// actual_len is guaranteed non-negative here
char *buf = malloc((size_t)actual_len);
if (!buf) return false;
read_data(buf, actual_len);
free(buf);
return true;
}
Exploited in the Wild
MaraDNS Integer Underflow (MaraDNS, 2024)
CVE in MaraDNS DNS server where an integer underflow in the decomp_get_rddata function during DNS packet decompression allows remote attackers to cause denial of service. When rdlength is smaller than rdata, the subtraction underflows, causing impossible memory allocation attempts.
NVIDIA Triton Inference Server (NVIDIA, 2025)
Integer underflow vulnerability in NVIDIA Triton Inference Server enabling denial of service or potential memory corruption through crafted inference requests.
VMware Products (VMware, 2025)
Integer underflow vulnerabilities reported in VMware Cloud Foundation, VMware Fusion, and VMware Workstation affecting virtualization security.
Tools to test/exploit
-
UBSan — detects signed integer underflow (undefined behavior).
-
AddressSanitizer — detects memory issues resulting from underflow.
-
AFL++ — fuzzer for discovering underflow conditions through edge cases.
CVE Examples
-
CVE-2022-42475 — Fortinet FortiOS SSL-VPN heap underflow exploited in the wild.
-
CVE-2023-27997 — Fortinet FortiGate buffer underflow RCE.
-
CVE-2024-3094 — XZ Utils backdoor involving integer manipulation.
References
-
MITRE. "CWE-191: Integer Underflow (Wrap or Wraparound)." https://cwe.mitre.org/data/definitions/191.html
-
CERT. "INT30-C. Ensure that unsigned integer operations do not wrap." https://wiki.sei.cmu.edu/confluence/display/c/INT30-C