Wiki Markup |
---|
The macro expansion must always be parenthesized to protect any lower-precedence operators from the surrounding expression. See also \[[PRE00-A. Prefer inline functions to macros|PRE00-A. Prefer inline functions to macros]\] and \[[PRE01-A. Use parentheses within macros around variable names|PRE01-A. Use parentheses within macros around variable names]\]. |
...
As a result, the invocation
Code Block | ||
---|---|---|
| ||
int a = 81 / CUBE(i); |
expands to
Code Block | |
---|---|
#FFcccc | int a = 81 / i * i * i; |
which evaluates as
Code Block | bgColor | #FFcccc
---|
int a = ((81 / i) * i) * i); /* evaluates to 243 */ |
while which is not the desired behavior is
...
bgColor | #FFcccc |
---|
...
.
Compliant Solution
By parenthesizing the macro expansion, the CUBE()
macro expands correctly (when invoked in this manner).
Code Block | ||
---|---|---|
| ||
#define CUBE(X) ((X) * (X) * (X)) int i = 3; int a = 81 / CUBE(i); |
However, if a parameter appears several times in the expansion, the macro may not work properly if the actual argument is an expression with side effects. Given the CUBE()
macro above, the invocation
Code Block | ||
---|---|---|
| ||
int a = 81 / CUBE(i++);
|
expands to
Code Block | |
---|---|
#ccccff | |
int a = 81 / (i++ * i++ * i++);
|
Wiki Markup |
---|
which is undefined (see \[[EXP30|EXP30-C. Do not depend on order of evaluation between sequence points]\]). |
Risk Assessment
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
PRE02-A | 1 (low) | 1 (unlikely) | 3 (low) | P3 | L3 |
Examples of vulnerabilities resulting from the violation of this recommendation can be found on the
CERT website.
References
Wiki Markup |
---|
\[[Summit 05|AA. C References#Summit 05]\] Question 10.1 \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.10, "Preprocessing directives," and Section 5.1.1, "Translation environment" |