Standard-layout types can be used to communicate with code written in other programming languages, as the layout of the type is strictly specified. The C++ Standard, Clause 9 [class], paragraph 7 [ISO/IEC 14882-2014], defines standard-layout classes as ones that:
- do not have virtual functions
- have the same access control for all nonstatic data members
- has no base classes of the same type as the first nonstatic data member
- has nonstatic data members declared in only one class within the class hierarchy
- recursively, do not have nonstatic data members of nonstandard-layout type
An execution boundary is the delimitation between code compiled by differing compilers, including different versions of a compiler produced by the same vendor. For instance, a function may be declared in a header file, but defined in a library that is loaded at runtime. The execution boundary is between the call site in the executable, and the function implementation in the library. Such boundaries are also called ABI boundaries, as they relate to the interoperability of application binaries.
Assumptions must not be made concerning the specific layout of objects with nonstandard-layout types. For objects compiled by one compiler that are referenced by code compiled by a different compiler, such assumptions cause correctness and portability concerns. The layout of the object generated by the first compiler is not guaranteed to be identical to the layout generated by the second compiler, even if both compilers are conforming C++ implementations. However, some implementations may document binary compatibility guarantees that can be relied on for passing nonstandard-layout objects between execution boundaries.
A special instance of this guidance involves non-C++ code compiled by a different compiler, such as C standard library implementations that are exposed via the C++ standard library. C standard library functions are exposed with C++ signatures, and the type system frequently assists in ensuring that types match appropriately. This disallows passing a pointer to a C++ object to a function expecting a char *
without additional work to suppress the type mismatch. However, some C standard library functions accept a void *
, for which any C++ pointer type will suffice. Passing a pointer to a nonstandard-layout type in this situation results in unspecified behavior, as it depends on the behavior of the other language as well as the layout of the given object.
Noncompliant Code Example
In this noncompliant code example, std::memset()
is used to clear the internal state of an object that is not of a standard-layout type. An implementation may store a vtable within the object instance, which is subsequently overwritten by the call to std::memset()
, leading to undefined behavior when virtual method dispatch is required.
#include <cstring> struct S { int i, j, k; // ... virtual void f(); }; void f() { S *s = new S; // ... std::memset(s, 0, sizeof(S)); // ... s->f(); }
Compliant Solution
In this compliant solution the data members of S
are cleared explicitly instead of calling std::memset()
:
struct S { int i, j, k; // ... virtual void f(); void clear() { i = j = k = 0; } }; void f() { S *s = new S; // ... s->clear(); // ... s->f(); }
Risk Assessment
The effects of passing objects of nonstandard-layout type across execution boundaries depends on what operations are performed on the object within the callee as well as what subsequent operations are performed on the object from the caller, and can range from correct or benign behavior to undefined behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP60-CPP | High | Probable | Medium | P12 | L1 |
Automated Detection
-Wdynamic-class-memaccess
Tool | Version | Checker | Description |
---|---|---|---|
3.9 |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C++ Coding Standard | EXP58-CPP. Do not pass a reference or nontrivially copyable type to va_start |
Bibliography
[ISO/IEC 14882-2014] | Clause 9, "Classes" |