Safeguard
Application Security•

CWE-680 Integer Overflow to Buffer Overflow: Allocation Math Gone Wrong

When a size calculation overflows, malloc hands back a tiny buffer and the next copy runs far past it. Here is how CWE-680 works and how to guard the arithmetic.

Safeguard Security Team
4 min read

CWE-680, Integer Overflow to Buffer Overflow, is a two step bug. First a program multiplies or adds numbers to work out how much memory to allocate. The result wraps around and comes out smaller than intended. Second, the program writes as much data as it originally planned for, into the undersized buffer.

MITRE lists memory-unsafe languages, C and C++ among them, as the platforms. It is a problem for anyone parsing sizes, counts or lengths that come from outside the process: image decoders, network protocols, file formats.

How it happens

MITRE's own example is an image processing routine. It allocates a table for images, each described as 10 kB, using this calculation:

// Vulnerable: sizeof(img_t) * num_imgs can overflow
img_t *table_ptr;
int num_imgs = get_num_imgs();
table_ptr = (img_t *)malloc(sizeof(img_t) * num_imgs);

As num_imgs grows large, the multiplication wraps and a very small list gets allocated. If later code treats the table as num_imgs entries long, it reads and writes out of bounds.

Picture the numbers on a 32 bit counter. A count near four billion multiplied by a modest element size does not produce a huge number. It produces a small one, because the high bits are silently dropped. The allocator is happy to give you that small block.

Two observed CVEs show variations. 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 then heap memory corruption. CVE-2017-1000121 is a chain where unchecked message size metadata allows an integer overflow leading to a buffer overflow.

What an attacker gains

MITRE lists several impacts at once: modify memory, denial of service through crash, exit or restart, and execution of unauthorized code or commands. The scopes affected are integrity, availability and confidentiality. The attacker's lever is the number they control, whether a count in a header or a length field in a message.

How to find it

  • Static analysis. MITRE notes SAST can find some instances by modelling data flow and control flow. Look for arithmetic on externally supplied values that feeds straight into an allocation.
  • Compiler runtime checks. MITRE also points to automated dynamic analysis, using tools integrated at compile time that insert runtime error checking for memory safety errors.
  • Code review of every malloc, calloc, new[] and realloc whose size argument is computed, not constant.

How to fix it

The MITRE record carries no mitigation text for this entry, so these steps come from the weakness itself. The fault is arithmetic that is not checked, so check it.

  1. Validate sizes and counts against a sane upper bound before using them.
  2. Check for overflow before you multiply.
  3. Prefer calloc(count, size), which implementations are expected to check for overflow, over a hand-written multiplication.
  4. Keep the types consistent. Do not narrow a 64 bit value to 32 bits on the way to an allocation.
// Fixed: bound the count, and check the multiplication
#define MAX_IMGS 10000
size_t n = (size_t)get_num_imgs();
if (n == 0 || n > MAX_IMGS) return -1;
if (n > SIZE_MAX / sizeof(img_t)) return -1;
img_t *table_ptr = malloc(n * sizeof(img_t));
if (table_ptr == NULL) return -1;

Native parsers also arrive as dependencies. To see whether your dependency list contains known vulnerabilities, run the free scan at gold.safeguard.sh/scan. It runs in the browser, needs no login, and the file stays on your machine.

Quick check

Why is a small allocation followed by a large write the core of this bug?

Because the size used to allocate and the size used to copy come from the same input but go through different arithmetic, or the allocation arithmetic wraps. The buffer ends up smaller than the data written into it.

Is casting a 64 bit value to 32 bits a CWE-680 problem by itself?

On its own it is an incorrect numeric conversion (CWE-681). It becomes CWE-680 when the truncated value feeds an allocation size and a later write overruns it.

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.