C Basics: Check Multiplication Before Allocating an Array
A count can fit in size_t while count multiplied by element size does not. Validate the multiplication before asking malloc for storage.
Prepare a scratch directory
Tested on Linux amd64 with GCC 14.2.0. You need GCC with C17 support, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. No external library is required.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1Run the example
Save this as checked-allocation-size-demo.c:
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
static bool allocation_size(size_t count, size_t element_size,
size_t *byte_count) {
if (element_size != 0 && count > SIZE_MAX / element_size) {
return false;
}
*byte_count = count * element_size;
return true;
}
int main(void) {
size_t byte_count = 0;
size_t element_count = 3;
int *values = NULL;
printf("Overflow rejected: %s\n",
allocation_size(SIZE_MAX, 2, &byte_count) ? "no" : "yes");
if (!allocation_size(element_count, sizeof *values, &byte_count)) {
fputs("Array size overflow\n", stderr);
return 1;
}
values = malloc(byte_count);
if (values == NULL) {
fputs("Allocation failed\n", stderr);
return 1;
}
for (size_t index = 0; index < element_count; ++index) {
values[index] = (int)index + 10;
}
printf("Values: %d %d %d\n", values[0], values[1], values[2]);
free(values);
return 0;
}Compile and run it. The program runs only if compilation succeeds:
gcc -std=c17 -Wall -Wextra -Werror -pedantic checked-allocation-size-demo.c -o checked-allocation-size-demo &&
./checked-allocation-size-demoObserved output:
Overflow rejected: yes
Values: 10 11 12Read the result
The division guard runs before multiplication. The deliberately oversized request is rejected without allocating memory. The valid allocation is checked, initialized and freed.
Apply it carefully
A non-overflowing size can still be too large to allocate or too large for the application, so enforce a separate workload limit. The helper requires a non-null output pointer; its value is unchanged on failure. This example uses a positive element count and avoids the special behavior of zero-size allocation.
See the WG14 C draft, sections 6.2.5 and 7.22.3 for the underlying language rules.
Clean up
Remove only the source and executable created here, return to the starting directory, and remove the empty practice directory:
rm -- checked-allocation-size-demo.c checked-allocation-size-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directoryIf the directory is not empty, inspect its contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.