Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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
bgColor#FFcccc
int a = 81 / CUBE(i);

expands to

bgColor
Code Block
#FFcccc
int a = 81 / i * i * i;

which evaluates as

#FFcccc
Code Block
bgColor
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
bgColor#ccccff
#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
bgColor#ccccff
int a = 81 / CUBE(i++);

expands to

bgColor
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"