Versions Compared

Key

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

An unsafe function-like macro is one that, when expanded, evaluates its argument more than once or doesn't evaluate it at all. Contrasted with function calls, which always evaluate each of their arguments exactly once, unsafe function-like macros often have unexpected and surprising effects and lead to subtle, hard to find defects. (see See guideline PRE31-C. Avoid side-effects in arguments to unsafe macros.) . Consequently, every function-like macro should evaluate each of its arguments exactly once. Alternatively and preferably, defining function-like macros should be avoided in favor of inline functions. (see See guideline PRE00-C. Prefer inline or static functions to function-like macros.).

Anchor
nce_multiple_evaluation
nce_multiple_evaluation

Noncompliant Code Example (

...

Multiple Argument Evaluation)

The most severe problem with unsafe function-like macros is side effects of macro arguments, as shown in this noncompliant code example.

...

The invocation of the ABS() macro in this noncompliant code example expands to the code below. Since the resulting expression modifies an object more than once, its behavior is undefined. (see See guideline EXP30-C. Do not depend on order of evaluation between sequence points.).

Code Block
bgColor#FFcccc
m = (((++n) < 0) ? -(++n) : (++n));  /* undefined behavior */

Anchor
cs_inline_function
cs_inline_function

Compliant Solution (

...

Inline Function)

A possible and preferable compliant solution is to define an inline function with equivalent but safe semantics:

...

Anchor
cs_language_extension
cs_language_extension

Compliant Solution (

...

Language Extension)

Some implementations provide language extensions that make it possible to define safe function-like macros such as the macro ABS() above that would otherwise require evaluating their arguments more than once. For example, the gcc extension Statements and Declarations in Expressions makes it possible to implement the macro ABS() in a safe way. Note, however, that since relying on implementation-defined extensions introduces undesirable platform dependencies that may make the resulting code non-portable, such solutions should be avoided in favor of portable ones wherever possible. (see See guideline MSC14-C. Do not introduce unnecessary platform dependencies.).

Code Block
bgColor#ccccff
#define ABS(x) ({int tmp = (x); tmp < 0 ? -tmp : tmp; })

...

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Other Languages

Related Guidelines

This rule appears in the C++ Secure Coding Standard as : PRE12-CPP. Do not define unsafe macros.

Bibliography

Wiki Markup
\[[ISO/IEC 9899:1999|AA. Bibliography#ISO/IEC 9899-1999]\] Section 5.1.2.3, "Program execution"

...