...
Code Block | ||||
---|---|---|---|---|
| ||||
// s.h struct S { char c; int a; }; void init_s(S &s); // s.cpp #include "s.h" void init_s(S &s); { s.c = 'a'; s.a = 12; } // a.cpp #pragma pack(push, 1) #include "s.h" #pragma pack(pop) void f() { S s; init_s(s); } |
Implementation Details
It is possible for the preceding noncompliant code example to result in a.cpp
allocating space for an object with a different size than expected by init_s()
in s.cpp
. When translating s.cpp
, the layout of the structure may include padding bytes between the c
and a
data members. When translating a.cpp
, the layout of the structure may remove those padding bytes as a result of the #pragma pack
directive, and so the object passed to init_s()
may be smaller than expected. As a resultConsequently, when init_s()
initializes the data members of s
, it may result in a buffer overrun.
...
Violating the ODR results in undefined behavior, which can result in exploits as well as denial-of-service attacks. As the paper by Quinlan et al. shows 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. This is where 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 et al. and colleagues for more details. However, note that the attacker must have access to the system building the code to introduce the malicious class.
...