Some operators do not evaluate their operands beyond the type information they the operands provide. When using one of these operators, do not pass an operand which that would otherwise yield a side effect , as since the side effect will not be generated.
The sizeof
operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. In most cases, the operand is not evaluated. A possible exception is when the type of the operand is a variable length array type (VLA); then the expression is evaluated. When part of the operand of the sizeof operator is a VLA type and when changing the value of the VLA's size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated. (see See unspecified behavior 22.).
The operands operand passed to_Generic
and _Alignof
are Alignof
is never evaluated, despite not being an expression. For instance, if the operand is a VLA type and the VLA's size expression contains a side effect, that side effect is never evaluated.
The operand used in the controlling expression of a _Generic
selection expression is never evaluated.
Providing an expression that appears to produce side effects may be misleading to programmers who are not aware that these expressions are not evaluated, and in the case of a VLA used in sizeof
, have unspecified results. As a result, programmers may make invalid assumptions about program state, leading to errors and possible software vulnerabilities.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> void func(void) { int a = 14; int b = sizeof(a++); printf("%d, %d\n", a, b); } |
Consequently, the value of a
after b
has been initialized is 14.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> void func(void) { int a = 14; int b = sizeof(a); ++a; printf("%d, %d\n", a, b); } |
...
Noncompliant Code Example (sizeof
, VLA)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> #include <stdio.h> void f(size_t n) { /* n must be incremented */ size_t a = sizeof(int[++n]); /* n need not be incremented */ size_t b = sizeof(int[++n % 1 + 1]); printf("%zu, %zu, %zu\n", a, b, n); /* ... */ } |
...
...
Compliant Solution (sizeof
, VLA)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> #include <stdio.h> void f(size_t n) { size_t a = sizeof(int[n + 1]); ++n; size_t b = sizeof(int[n % 1 + 1]); ++n; printf("%zu, %zu, %zu\n", a, b, n); /* ... */ } |
Noncompliant Code Example (_Generic
)
This noncompliant solution code example attempts to modify a variable's value as part of the _Generic
association list selection control expression. The user may have expected the value of a
to be 2
because the type of the variable is int
programmer may expect that a
is incremented, but because _Generic
does not evaluate its operandscontrol expression, the the value of a
is not modified.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #define S(val) _Generic(val, int : val = 2, \ short : val = 3, \ default : val = 1) void func(void) { int a = 0; int b = S(a++); printf("%d, %d\n", a, b); } |
Compliant Solution (_Generic
)
This In this compliant solution uses the result of the _Generic
operator to assign the correct value to a
., a is incremented outside of the _Generic
selection expression:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #define S(val) _Generic(val, int : 2, \ short : 3, \ default : 1) void func(void) { int a = 0; int ab = S(a); ++a; printf("%d, %d\n", a, b); } |
Noncompliant Code Example (_Alignof
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef<stdio.h> void func(void) { int val = 0; /* ... */ size_t align = _Alignof(int[++val]); printf("%zu, %d\n", align, val); /* ... */ } |
Compliant Solution (_Alignof
)
The This compliant solution moves the expression out of the _Alignof
operator.:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef<stdio.h> void func(void) { int val = 0; /* ... */ ++val; intsize_t align = _Alignof(int[val]); printf("%zu, %d\n", align, val); /* ... */ } |
Exceptions
EXP44-C-EX1: Reading a volatile
-qualified value is a side-effecting operation. However, accessing a value through a volatile
-qualified type does not guarantee side effects will happen on the read of the value unless the underlying object is also volatile
-qualified. Idiomatic reads of a volatile
-qualified object are permissible as an operand to a sizeof()
, _Alignof()
, or _Generic
expression, as in the following example:
Code Block | ||||
---|---|---|---|---|
| ||||
void f(void) {
int * volatile v;
(void)sizeof(*v);
} |
Risk Assessment
If expressions that appear to produce side effects are supplied to an operator that does not evaluate its operands, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP44-C | Low | Unlikely | Low | P3 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| alignof-side-effect | Fully checked | ||||||
Axivion Bauhaus Suite |
| CertC-EXP44 | |||||||
Clang |
| -Wunevaluated-expression | Can diagnose some instance of this rule, but not all (such as the _Alignof NCCE). | ||||||
CodeSonar |
| LANG.STRUCT.SE.SIZEOF LANG.STRUCT.SE.CGEN | Side effects in sizeof Side Effects in C Generic Selection | ||||||
Compass/ROSE |
Coverity |
| MISRA C 2004 Rule 12.3 | Partially implemented |
| CC2.EXP06 | Fully implemented | |||||||
Helix QAC |
| C3307 | |||||||
Klocwork |
| MISRA.SIZEOF.SIDE_EFFECT | |||||||
LDRA tool suite |
| 54 S, 653 S | Fully implemented |
Parasoft C/C++test |
| CERT_C-EXP44-a | Object designated by a volatile lvalue should not be accessed in the operand of the sizeof operator | ||||||
PC-lint Plus |
| 9006 | Partially supported: reports use of sizeof with an expression that would have side effects | ||||||
| Checks for situations when side effects of specified expressions are ignored (rule fully covered) | ||||||||
PVS-Studio |
| V568 | |||||||
RuleChecker |
| alignof-side-effect | Fully checked |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
---|---|---|
CERT C |
EXP52-CPP. |
Do not rely on side effects |
...
in unevaluated operands | Prior to 2018-01-12: CERT: Unspecified Relationship |
...