Parenthesize all variable names in macro definitions. See also [[PRE02]].
Non-Compliant Code Example
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 */
while the desired behavior is
int a = 81 / ( (2 + 1) * (2 + 1) * (2 + 1)); /* evaluates to 3 */
Compliant Solution
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);
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
int a = 81 / CUBE(i++); {code:bgColor=#ccccff} expands to
int a = 81 / (i++ * i++ * i++);
which is undefined (see [[EXP30]]).
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 can be found on the
CERT website.
References
[[Summit 05]] Question 10.1
[[ISO/IEC 9899-1999]] Section 6.10, "Preprocessing directives," and Section 5.1.1, "Translation environment"