CWE-681, Incorrect Conversion between Numeric Types, applies whenever data moves from one numeric type to another and the value changes along the way. MITRE gives the example of long to integer: data can be omitted or translated in a way that produces unexpected values.
On its own that is a correctness bug. It turns into a security bug when the resulting value is used in a sensitive context, such as sizing memory or deciding whether something is allowed.
How it happens
Three common shapes show up in MITRE's observed examples:
- Narrowing. CVE-2021-43537 is a chain in a web browser where an unsigned 64 bit integer is forcibly cast to a 32 bit integer, potentially leading to an integer overflow and heap memory corruption.
- Signedness. CVE-2007-4268 is a chain where an integer signedness error passes a signed comparison, leading to a heap overflow.
- Sign extension. CVE-2007-4988 involves a signed short width value in an image processor that is sign extended during conversion to unsigned int, which leads to an integer overflow and a heap-based buffer overflow.
A related entry, CVE-2022-2639, is a chain where an integer coercion error prevents a return value from indicating an error, leading to an out-of-bounds write.
A small illustration of the signedness case:
// Vulnerable: a negative length passes the check, then becomes huge
int len = read_length_from_packet(); // may be negative
if (len > MAX_LEN) return -1; // -5 is not greater than MAX_LEN
memcpy(dst, src, len); // len converts to a very large size_t
What an attacker gains
MITRE says the program can end up using the wrong number and produce incorrect results. If that number allocates resources or feeds a security decision, a vulnerability follows. The record lists impact as integrity and unexpected state. What that means in practice depends on where the number lands, and the CVEs above landed in heap memory.
How to find it
MITRE notes static analysis can find some instances by modelling data flow. Turn on compiler warnings for sign comparison and narrowing, and treat them as errors on code that handles external input. In review, follow every value that arrives from a file or a socket to its first use and note each type change.
How to fix it
MITRE's guidance is short: avoid conversions between numeric types, and always check the allowed ranges.
- Use one type end to end for sizes and counts. In C that usually means
size_t. - Validate the range before converting, in both directions: lower bound as well as upper.
- Reject out of range values instead of clamping silently.
// Fixed: check both bounds before the conversion
int len = read_length_from_packet();
if (len < 0 || len > MAX_LEN) return -1;
memcpy(dst, src, (size_t)len);
If you are checking what native libraries you depend on, the free scan at gold.safeguard.sh/scan takes a dependency file in the browser, with no login, and nothing leaves your machine.
Quick check
Why does a negative length slip past a "less than max" check?
Because a negative signed value is less than the maximum, so the check passes. The later conversion to an unsigned size then turns it into a very large number.