...
The documentation for unsafe macros should warn against invoking them with arguments with side effects, but the responsibility is on the programmer using the macro. Because of the risks associated with their use, it is recommended that the creation of unsafe function-like macros be avoided. (see See PRE00-C. Prefer inline or static functions to function-like macros.).
This rule is similar to EXP44-C. Do not rely on side effects in operands to sizeof, _Alignof, or _Generic.
...
Note the comment warning programmers that the macro is unsafe. The macro can also be renamed ABS_UNSAFE() to make it clear that the macro is unsafe. This compliant solution, like all the compliant solutions for this rule, has undefined behavior if the argument to ABS() is equal to the minimum (most negative) value for the signed integer type type. (see See INT32-C. Ensure that operations on signed integers do not result in overflow for more information.).
Compliant Solution
This compliant solution follows the guidance of PRE00-C. Prefer inline or static functions to function-like macros by defining an inline function iabs() to replace the ABS() macro. Unlike the ABS() macro, which operates on operands of any type, the iabs() function will truncate arguments of types wider than int whose value is not in range of the latter type.
...
A more flexible compliant solution is to declare the ABS() macro using a _Generic selection. To support all arithmetic data types, this solution also makes use of inline functions to compute integer absolute values. (see See PRE00-C. Prefer inline or static functions to function-like macros and PRE12-C. Do not define unsafe macros.).
According to the C Standard, 6.5.1.1, paragraph 3 [ISO/IEC 9899:2011]:
...
The assert() macro is a convenient mechanism for incorporating diagnostic tests in code. (see See MSC11-C. Incorporate diagnostic tests using assertions.) . Expressions used as arguments to the standard assert() macro should not have side effects. The behavior of the assert() macro depends on the definition of the object-like macro NDEBUG. If the macro NDEBUG is undefined, the assert() macro is defined to evaluate its expression argument and, if the result of the expression compares equal to 0, call the abort() function. If NDEBUG is defined, assert is defined to expand to ((void)0). Consequently, the expression in the assertion is not evaluated, and no side effects it may have had otherwise take place in non-debugging executions of the code.
...
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| ASSERT_SIDE_EFFECTS | Can detect the specific instance where assertion contains an operation/function call that may have a side effect | |||||||
| ECLAIR |
| CC2.EXP31 CC2.PRE31 | Fully implemented | ||||||
| 9 S, 562 S, 572 S, 35 D, 1 Q | Fully implemented | |||||||
| Parasoft C/C++test | 9.5 | CODSTA-123 | Partially implemented | ||||||
| Polyspace Bug Finder | R2016a | MISRA2012-RULE-13_2 | Partial | ||||||
| PRQA QA-C |
| 3453, 3455, 3456 | Fully implemented |
Related Vulnerabilities
...