Safeguard
Application Security•

CWE-681 Incorrect Conversion Between Numeric Types Explained

Casting a long to an int or a signed value to unsigned can quietly change the number. CWE-681 is what happens when that wrong number reaches an allocation or a security check.

Safeguard Security Team
3 min read

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.

  1. Use one type end to end for sizes and counts. In C that usually means size_t.
  2. Validate the range before converting, in both directions: lower bound as well as upper.
  3. 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.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.