Parenthesize all variable names in macro definitions. See also [[PRE00-A. Prefer inline functions to macros]] and [[PRE02-A. Macro expansion should always be parenthesized for function-like macros]].
Non-Compliant Code Example (macros)
This CUBE()
macro definition is non-compliant because it fails to parenthesize the variable names.
#define CUBE(I) (I * I * I) int a = 81 / CUBE(2 + 1);
As a result, the invocation
int a = 81 / CUBE(2 + 1);
expands to
int a = 81 / (2 + 1 * 2 + 1 * 2 + 1); /* evaluates to 11 */
Which is clearly not the desired result.
Compliant Solution (macros)
Parenthesizing all variable names in the CUBE()
macro allows it to expand correctly (when invoked in this manner).
#define CUBE(I) ( (I) * (I) * (I) ) int a = 81 / CUBE(2 + 1);
Non-Compliant Code Example (EOF)
In this example, EOF
is defined without parenthesizing the -1
. Additionally, the programmer mistakenly omitted the comparison operator from the conditional statement. After macro expansion, the conditional will be incorrectly evaluated as a binary operation: c-1
.
#define EOF -1 /* ... */ if (c EOF) { /* ... */ }
Note that this example also violates [[MSC02-A. Avoid errors of omission]].
Compliant Solution (EOF)
Parenthesizing the -1
in the declaration of EOF
does not correct the omission of the comparison operator, but it does ensure the -1
is evaluated as a unary operation.
#define EOF (-1) /* ... */ if (c EOF) { /* ... */ }
The code above will fail compilation as after macro expansion the conditional will evaluate to c(-1)
. To fully correct this example the error of omission must also be addressed.
#define EOF (-1) /* ... */ if (c == EOF) { /* ... */ }
Risk Assessment
Failing to parenthesize around the variable names within a macro can result in unintended program behavior.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
PRE01-A |
1 (low) |
1 (unlikely) |
3 (low) |
P3 |
L3 |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Plum 85]]
[[Summit 05]] Question 10.1
[[ISO/IEC 9899-1999]] Section 6.10, "Preprocessing directives," and Section 5.1.1, "Translation environment"