Wiki Markup |
---|
Parenthesize all variable names in macro definitions. See also \[[PRE02-A. Macro expansion must always be parenthesized|PRE02-A. Macro expansion must always be parenthesized]\] and \[[PRE00-A. Prefer inline functions to macros|PRE00-A. Prefer inline functions to macros]\] . |
Non-Compliant Code Example
...
As a result, the invocation
Code Block | |
---|---|
#FFcccc | int a = 81 / CUBE(2 + 1); |
expands to
Code Block | ||
---|---|---|
| ||
int a = 81 / (2 + 1 * 2 + 1 * 2 + 1); /* evaluates to 11 */ |
while Which is clearly not the desired behavior is
Code Block | ||
---|---|---|
| ||
int a = 81 / ( (2 + 1) * (2 + 1) * (2 + 1)); /* evaluates to 3 */
|
result.
Compliant Solution
Parenthesizing all variable names in the CUBE()
macro allows it to expand correctly (when invoked in this manner).
Code Block | ||
---|---|---|
| ||
#define CUBE(I) ( (I) * (I) * (I) ) int a = 81 / CUBE(2 + 1); |
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++);
{code:bgColor=#ccccff}
expands to
|
int a = 81 / (i++ * i++ * i++);
...
Risk Assessment
Failing to parenthesize around the variable names within a macro can result in unexpected arithmetic results.
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 |
---|---|---|---|---|---|
PRE01-A | 1 (low) | 1 (unlikely) | 3 (low) | P3 | L3 |
Examples of vulnerabilities resulting from the violation of this recomendation 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" |