CertC-ARR01¶
Do not apply the sizeof operator to a pointer when taking the size of an array
Required inputs: IR
The
sizeof operator yields the size (in bytes) of its operand, which
can be an expression or the parenthesized name of a type. However, using the
sizeof operator to determine the size of arrays is error prone.
The
sizeof operator is often used in determining how much memory to
allocate via
malloc(). However using an incorrect size is a violation of
MEM35-C.
Allocate sufficient memory for an object.
Noncompliant Code Example
In this noncompliant code example, the function
clear() zeros the elements in an array. The function has one
parameter declared as
int array[] and is passed a static array consisting of 12
int as the argument. The function
clear() uses the idiom
sizeof(array) / sizeof(array[0]) to determine the number of
elements in the array. However,
array has a pointer type because it is a parameter. As a result,
sizeof(array) is equal to the
sizeof(int *). For example, on an architecture (such as IA-32)
where the
sizeof(int) == 4 and the
sizeof(int *) == 4, the expression
sizeof(array) / sizeof(array[0]) evaluates to 1, regardless of the
length of the array passed, leaving the rest of the array unaffected.
void clear(int array[]) {
for (size_t i = 0; i < sizeof(array) / sizeof(array[0]); ++i) {
array[i] = 0;
}
}
void dowork(void) {
int dis[12];
clear(dis);
/* ... */
}
Footnote 103 in subclause 6.5.3.4 of the C Standard [ ISO/IEC 9899:2011] applies to all array parameters:
When applied to a parameter declared to have array or function type, the
sizeofoperator yields the size of the adjusted (pointer) type.
Compliant Solution
In this compliant solution, the size of the array is determined inside the block in which it is declared and passed as an argument to the function:
void clear(int array[], size_t len) {
for (size_t i = 0; i < len; i++) {
array[i] = 0;
}
}
void dowork(void) {
int dis[12];
clear(dis, sizeof(dis) / sizeof(dis[0]));
/* ... */
}
This
sizeof(array) / sizeof(array[0]) idiom will succeed provided the
original definition of
array is visible.
Noncompliant Code Example
In this noncompliant code example,
sizeof(a) does not equal
100 * sizeof(int), because the
sizeof operator, when applied to a parameter declared to have
array type, yields the size of the adjusted (pointer) type even if the
parameter declaration specifies a length:
enum {ARR_LEN = 100};
void clear(int a[ARR_LEN]) {
memset(a, 0, sizeof(a)); /* Error */
}
int main(void) {
int b[ARR_LEN];
clear(b);
assert(b[ARR_LEN / 2]==0); /* May fail */
return 0;
}
Compliant Solution
In this compliant solution, the size is specified using the expression
len * sizeof(int):
enum {ARR_LEN = 100};
void clear(int a[], size_t len) {
memset(a, 0, len * sizeof(int));
}
int main(void) {
int b[ARR_LEN];
clear(b, ARR_LEN);
assert(b[ARR_LEN / 2]==0); /* Cannot fail */
return 0;
}
Risk Assessment
Incorrectly using the
sizeof operator to determine the size of an array can result in a
buffer overflow, allowing the execution of arbitrary code.
| Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| ARR01-C | High | Probable | Low | P18 | L1 |
Related Guidelines
| Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| CERT C | CTR01-CPP. Do not apply the sizeof operator to a pointer when taking the size of an array | Prior to 2018-01-12: CERT: Unspecified Relationship |
| CWE 2.11 | CWE-467, Use of sizeof() on a pointer type | Prior to 2018-01-12: CERT: |
| ISO/IEC TS 17961 | Taking the size of a pointer to determine the size of the pointed-to type [sizeofptr] | Prior to 2018-01-12: CERT: Unspecified Relationship |
| MITRE CWE | CWE-569 | Prior to 2018-01-12: |
| MITRE CWE | CWE-783 | Prior to 2018-01-12: |
Bibliography
| [ Drepper 2006] | Section 2.1.1, "Respecting Memory Bounds" |
| [ ISO/IEC 9899:2011] | Subclause 6.5.3.4, "The
sizeof and
_Alignof Operators"
|
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
sizeof_on_array_param |
Operand of “sizeof” shall not be an array parameter |
None |
False |
Options
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
This rule has no individual options.