...
There can be more than one definition of a class type, enumeration type, inline function with external linkage, class template, non-static function template, static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named
D
defined in more than one translation unit,....If the definitions of
D
satisfy all these requirements, then the program shall behave as if there were a single definition ofD
. If the definitions ofD
do not satisfy these requirements, then the behavior is undefined.
...
In this noncompliant code example, a class definition is introduced into two translation units using #include
. However, one of the translation units uses a common, implementation-defined defined #pragma
to specify structure field alignment requirements. Consequently, the two class definitions may have differing layouts in each translation unit, which is a violation of the ODR.
...
In this noncompliant code example, the constant object n
has internal linkage but is odr-used within f()
, which has external linkage. Because f()
is declared as an inline function, the definition of f()
must be identical in all translation units. However, each translation unit has a unique instance of n
, resulting in a violation of the One Definition RuleODR.
Code Block | ||||
---|---|---|---|---|
| ||||
const int n = 42; int g(const int &lhs, const int &rhs); inline int f(int k) { return g(k, n); } |
...
A compliant solution must change one of three factors: do it must not odr-use n
within f()
, it must declare n
such that it has external linkage, or do it must not use an inline definition of f()
.
If circumstances allow modification of the signature of g()
to accept parameters by value instead of by reference, then n
will not be odr-used within f()
because n
would then qualify as a constant expression. While this results in a compliant solution, This solution is compliant, but it is not ideal. It may not be possible (or desirable) to modify the signature of g(),
such as std::max()
from <algorithm>
. Also, due to because of the differing linkage used by n
and f()
, accidental violations of the One Definition Rule ODR are still likely if the definition of f()
is modified to odr-use n
.
...
In this compliant solution, the constant object n
is replaced with an enumerator of the same name. Named enumerations defined at namespace scope have the same linkage as the namespace they are contained in. The global namespace has external linkage, and so the definition of the named enumeration, and its contained enumerators, also have external linkage. While Although less aesthetically pleasing, this compliant solution does not suffer from the same maintenance burdens of the previous code because n
and f()
have the same linkage.:
Code Block | ||||
---|---|---|---|---|
| ||||
enum Constants { n = 42 }; int g(const int &lhs, const int &rhs); inline int f(int k) { return g(k, n); } |
Risk Assessment
Violating the ODR results in causes undefined behavior, which can result in exploits as well as denial-of-service attacks. As shown in "Support for Whole-Program Analysis and the Verification of the One-Definition Rule in C++" [Quinlan 06], failing to enforce the ODR enables a virtual function pointer attack known as the VPTR exploit. In this exploit, an object's virtual function table is corrupted so that calling a virtual function on the object results in malicious code being executed. See the paper by Quinlan and colleagues for more details. However, note that to introduce the malicious class, the attacker must have access to the system building the code to introduce the malicious class.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MSC52-CPP | High | Unlikely | High | P3 | L3 |
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
PRQA QA-C++ |
| 1067, 1509 |
Related Vulnerabilities
...