VNX-1325 – Improperly Controlled Sequential Memory Allocation

Overview

When memory is allocated in a loop and the loop count or individual allocation size comes from user-controlled input without a total cap, an attacker can exhaust available memory. The cumulative allocation may be orders of magnitude larger than any single checked value. This leads to OOM crashes, swap thrashing, or process termination — all denial-of-service conditions. Severity: Medium | CWE: CWE-1325 – Improperly Controlled Sequential Memory Allocation

Why This Matters

A common pattern is allocating a buffer for each item in a user-supplied list: if the user can specify 10 million items each requiring a 1 KB buffer, the total allocation is 10 GB. Without a total limit, even individually innocuous allocation sizes become dangerous at scale. This class of bug has affected JSON parsers, XML processors, and archive extraction utilities.

What Gets Flagged

// FLAGGED: malloc in loop, no total size tracking
int n = atoi(argv[1]);  // user-controlled count
for (int i = 0; i < n; i++) {
    buffers[i] = malloc(4096);  // total = n * 4096, no cap
}
// FLAGGED: make([]...) with user-supplied size
for i := 0; i < count; i++ {
    buf := make([]byte, size)  // no cumulative limit
    process(buf)
}
// FLAGGED: byte[] allocation with user-supplied size
int size = Integer.parseInt(request.getParameter("bufferSize"));
byte[] buffer = new byte[size];  // can be up to 2GB with one request

Remediation

// SAFE: Track total allocation and enforce cap
#define MAX_TOTAL_BYTES (64 * 1024 * 1024)  // 64 MB total

size_t total = 0;
for (int i = 0; i < n; i++) {
    if (total + 4096 > MAX_TOTAL_BYTES) {
        error("Allocation limit exceeded");
        break;
    }
    buffers[i] = malloc(4096);
    total += 4096;
}
// SAFE: Validate size before allocation
private static final int MAX_BUFFER_SIZE = 10 * 1024 * 1024; // 10 MB

int size = Integer.parseInt(request.getParameter("bufferSize"));
if (size < 0 || size > MAX_BUFFER_SIZE) {
    throw new IllegalArgumentException("Buffer size out of range");
}
byte[] buffer = new byte[size];
// SAFE: Cap individual and total allocations
const maxTotalBytes = 64 * 1024 * 1024

var totalAllocated int64
for i := 0; i < count; i++ {
    if totalAllocated+int64(size) > maxTotalBytes {
        return fmt.Errorf("allocation limit exceeded")
    }
    buf := make([]byte, size)
    totalAllocated += int64(size)
    process(buf)
}

References