Integer overflow and allocation size checks¶
Integer arithmetic can produce a value outside a type's representable range. In C and C++, unsigned arithmetic wraps modulo the type's range; signed overflow generally has undefined behavior. Neither should be used accidentally to calculate buffer sizes. A wrapped allocation size can reserve less memory than a later write expects. SEI CERT INT30-C covers unsigned wrapping and precondition checks.
Trust boundary: a caller-controlled record count must not determine memory allocation or pointer arithmetic until both representable range and application limits are checked.
Unsafe example¶
/* count comes from an untrusted document. */
size_t bytes = count * sizeof(struct record);
struct record *records = malloc(bytes);
/* Later code assumes space for count records. */
Safer example: check before multiplication¶
This C99 helper calculates the size; the caller still needs to check allocation success. The application policy permits 1–10,000 records.
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
struct record {
uint32_t id;
char label[64];
};
bool record_bytes(size_t count, size_t *bytes) {
if (bytes == NULL || count == 0 || count > 10000) {
return false;
}
if (count > SIZE_MAX / sizeof(struct record)) {
return false;
}
*bytes = count * sizeof(struct record);
return true;
}
The division checks whether multiplication is representable without performing the dangerous multiplication first. The separate business limit stops a valid but unreasonable allocation. Check any added header or terminator size too: before a + b, ensure a <= SIZE_MAX - b. Checking the result after signed overflow is too late because undefined behavior has already occurred.
Validate parsed numeric input before converting it to size_t. A negative signed value can become a large unsigned value, and an earlier narrowing conversion can discard bits. Keep the validated count alongside the allocation; do not allocate with one count and iterate using the original unvalidated value. C++ containers handle allocation bookkeeping but still require input limits and careful conversions.
Regression test¶
Assert that 1 and 10,000 produce the expected sizes; reject 0, 10,001, SIZE_MAX, and a null output pointer. Test the parser separately with a negative string and an integer outside the accepted range. Do not attempt enormous allocations to test arithmetic rejection. Compile local C/C++ tests with strong warnings and available undefined-behavior sanitizers.
Related: memory safety and resource exhaustion.
References: CWE-190 — integer overflow or wraparound and CWE-131 — incorrect calculation of buffer size.