Some expressions involve operands that are unevaluated. According to the C++ Standard, [expr], paragraph 8 [ISO/IEC 14882-2014]:
In some contexts, unevaluated operands appear. An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming of objects or functions does not, by itself, require that a definition be provided. — end note]
Because an unevaluated operand in an expression is not evaluated, no side effects from that operand will be triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effected in unevaluated operands.
The following expressions do not evaluate their operands: sizeof()
, typeid()
, noexcept()
, decltype()
, and declval()
.
Noncompliant Code Example (sizeof
)
In this noncompliant code example, the expression a++
is not evaluated:
#include <iostream> void f() { int a = 14; int b = sizeof(a++); std::cout << a << ", " << b << std::endl; }
Consequently, the value of a
after b
has been initialized is 14.
Compliant Solution (sizeof
)
In this compliant solution, the variable a
is incremented outside of the sizeof
operator:
#include <iostream> void f() { int a = 14; int b = sizeof(a); ++a; std::cout << a << ", " << b << std::endl; }
Noncompliant Code Example (decltype
)
In this noncompliant code example, the call to g()
is not evaluated within the decltype
specifier:
#include <iostream> static int glob = 100; int g() { return ++glob; } void f() { decltype(g()) h = 12; std::cout << glob; }
Consequently, the value of glob remains 14. The function call syntax is used within decltype
to distinguish between the return type of g()
and the function type of g
, but the call is never evaluated.
Compliant Solution (decltype
)
In this compliant solution, g()
is called outside of the decltype
specifier, so that it is evaluated as desired:
#include <iostream> static int glob = 100; int g() { return ++glob; } void f() { decltype(g()) h = 12; g(); std::cout << glob; }
Risk Assessment
If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP32-CPP | Low | Unlikely | Low | P3 | L3 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C Coding Standard | EXP44-C. Do not rely on side effects in operands to sizeof, _Alignof, or _Generic |
Bibliography
[ISO/IEC 14882-2014] | Clause 5, "Expressions" 20.2.5, "Function template declval " |