Do not hard code the size of a type into an application. Because of alignment, padding, and differences in basic types (e.g., 32-bit versus 64-bit pointers), the size of most types can vary between compilers and even versions of the same compiler. Using the sizeof
operator to determine sizes improves the clarity of what is meant and ensures that changes between compilers or versions will not affect the code.
Type alignment requirements can also affect the size of structures. For example, the size of the following structure is implementation defined:
struct s { int i; double d; };
Assuming 32-bit integers and 64-bit doubles, for example, the size can range from 12 or 16 bytes, depending on alignment rules.
Noncompliant Code Example
This noncompliant code example attempts to declare a two-dimensional array of integers with variable length rows. On a platform with 64-bit integers, the loop will access memory outside the allocated memory section.
/* assuming 32-bit pointer, 32-bit integer */ size_t i; int **matrix = (int **)calloc(100, 4); if (matrix == NULL) { /* handle error */ } for (i = 0; i < 100; i++) { matrix[i] = (int *)calloc(i, 4); if (matrix[i] == NULL) { /* handle error */ } }
Compliant Solution
This compliant solution replaces the hard-coded value 4
with sizeof(int *)
.
size_t i; int **matrix = (int **)calloc(100, sizeof(*matrix)); if (matrix == NULL) { /* handle error */ } for (i = 0; i < 100; i++) { matrix[i] = (int *)calloc(i, sizeof(**matrix)); if (matrix[i] == NULL) { /* handle error */ } }
Also see MEM02-C. Immediately cast the result of a memory allocation function call into a pointer to the allocated type for a discussion on the use of the sizeof
operator with memory allocation functions.
Exceptions
EXP09-EX1: C99 explicitly declares sizeof(char) == 1
. So any sizes based on characters or character arrays may be evaluated without using sizeof
. This does not apply to char*
or any other data types.
Risk Assessment
Porting code with hard-coded sizes can result in a buffer overflow or related vulnerability.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
EXP09-C |
high |
unlikely |
medium |
P6 |
L2 |
Automated Detection
Compass/ROSE can detect violations of this recommendation. In particular, it looks for the size argument malloc()
, calloc()
, or realloc()
, and flags when it does not find a sizeof
operator in the argument expression. It does not flag if the return value is assigned to a char *
, in this case a string is being allocated, and sizeof
is unnecessary because sizeof(char) == 1
.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C++ Secure Coding Standard as EXP09-CPP. Use sizeof to determine the size of a type or variable.
References
[[ISO/IEC 9899:1999]] Section 6.2.6, "Representations of types," and Section 6.5.3.4, "The sizeof operator"