parts/6.37.Type-breakingReinterpretationOfData-AMV.md

6.37 Type-breaking Reinterpretation of Data [AMV]

6.37.1 Applicability to language

The vulnerability as documented in ISO IEC 24772-1 clause 6.37 applies to C++. The language mechanisms where type-breaking reinterpretation of data can happen involve unions and std::bit_cast. For type-breaking reinterpretation involving pointers or references see 6.11 Pointer Type Conversions [HFC].

In C++, the issue of casting vulnerabilities are mitigated by the fact that the C++ named casts, i.e., reinterpret_cast, const_cast, static_cast, dynamic_cast, and std::bit_cast, are easily identified, e.g., by text search for more careful review. C-style casts do not share this property and therefore should be prohibited. In addition, C++ named casts include some compile-time checks, and in the case of dynamic_cast run-time checks, that help avoid some but not all vulnerabilities.

Of the available "_cast" operations, only std::bit_cast provides reinterpretation of data values, and only reinterpret_cast allow the reintepretation of data as a different type within limits. For uses of reinterpret_cast see 6.11 Pointer Type Conversions [HFC]. The named casts static_cast, dynamic_cast, and const_cast perform type conversions and not reintepretation of bits and thus don’t have this vulnerability but are subject to potential conversion errors (see 6.6 Conversion Errors [FLC]).

Reading a union member that was not previously written is undefined behaviour except for a few cases described by ISO/IEC 14882:2020 clause [class.mem.general]. The reinterpretation of data values via different union members that is common practice in C is undefined behaviour in C++. The type std::variant provides a similar mechanism to union but prevents reading an inactive member.

If there is no value of the target type corresponding to the bit representation of the source type’s value, using std::bit_cast is undefined behaviour, such as in the following example.

enum E { one, two, four=4 };
constexpr auto x = std::bit_cast<E>(42); // 42 is not representable by E

C++ also provides <type_traits>, such as std::is_layout_compatible, that can be used to ensure the legality of a specific std::bit_cast.

A legacy means of “bit casting” is the use of memcpy to transfer the bytes of an object’s representation to another object of a different type. Except for cases that are well-defined with std::bit_cast, such use of memcpy to reinterpret data values is undefined behaviour.

6.37.2 Avoidance mechanisms for language users

To avoid the vulnerability or mitigate its ill effects, C++ software developers can: