Changeset 205066 in webkit
- Timestamp:
- Aug 26, 2016 7:39:39 PM (8 years ago)
- Location:
- trunk/Source/WTF
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r205062 r205066 1 2016-08-26 JF Bastien <jfbastien@apple.com> 2 3 bitwise_cast uses inactive member of union 4 https://bugs.webkit.org/show_bug.cgi?id=161244 5 6 Reviewed by Benjamin Poulain. 7 8 * wtf/Compiler.h: 9 Add COMPILER_HAS_CLANG_FEATURE 10 * wtf/StdLibExtras.h: 11 (WTF::bitwise_cast): 12 Fix C++ UB, add trivially-copyable check. 13 14 bitwise_cast stores into a union with one type and reads with 15 another, which is technically C++ undefined behavior because it's 16 accessing the wrong active member of the union. The better way to 17 do this is through memcpy, which compilers optimize as well 18 because it's known-size in known-not-to-escape storage (for small 19 types they'll inline and then convert stack memory access to SSA 20 values which may be in-register if that makes sense, which would 21 be a move between int/FP registers at worst). 22 23 The C++ Standard's section [basic.types] explicitly blesses memcpy: 24 25 For any trivially copyable type T, if two pointers to T point to 26 distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a 27 base-class subobject, if the underlying bytes (1.7) making up obj1 28 are copied into obj2, 42 obj2 shall subsequently hold the same 29 value as obj1. 30 31 [Example: 32 T* t1p; 33 T* t2p; 34 // provided that t2p points to an initialized object ... 35 std::memcpy(t1p, t2p, sizeof(T)); 36 // at this point, every subobject of trivially copyable type in *t1p contains 37 // the same value as the corresponding subobject in *t2p 38 — end example ] 39 40 Whereas section [class.union] says: 41 42 In a union, at most one of the non-static data members can be 43 active at any time, that is, the value of at most one of the 44 non-static data members can be stored in a union at any time. 45 46 While we're at it, checking that sizeof(To) == sizeof(From) is 47 good, but we should also check that both types are trivially 48 copyable (can have a ctor, no dtor, and copy is defaulted as if by 49 memcpy for type and all subtypes). Unfortunately that trait isn't 50 implemented consistently in all recent compiler+stdlib 51 implementations, but recent clang has an equivalent builtin 52 (other compilers simply won't do the check, and will break on bots 53 with the right compilers which is better than the current silent 54 breakage). This builtin hack also avoids #include <type_traits> 55 which really doesn't save much. 56 1 57 2016-08-26 Johan K. Jensen <johan_jensen@apple.com> 2 58 -
trunk/Source/WTF/wtf/Compiler.h
r204433 r205066 36 36 #define COMPILER_QUIRK(WTF_COMPILER_QUIRK) (defined WTF_COMPILER_QUIRK_##WTF_COMPILER_QUIRK && WTF_COMPILER_QUIRK_##WTF_COMPILER_QUIRK) 37 37 38 /* COMPILER_HAS_CLANG_BUILTIN() - w ether the compiler supports a particular clang builtin. */38 /* COMPILER_HAS_CLANG_BUILTIN() - whether the compiler supports a particular clang builtin. */ 39 39 #ifdef __has_builtin 40 40 #define COMPILER_HAS_CLANG_BUILTIN(x) __has_builtin(x) … … 43 43 #endif 44 44 45 /* COMPILER_HAS_CLANG_HEATURE() - whether the compiler supports a particular language or library feature. */ 46 /* http://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension */ 47 #ifdef __has_feature 48 #define COMPILER_HAS_CLANG_FEATURE(x) __has_feature(x) 49 #else 50 #define COMPILER_HAS_CLANG_FEATURE(x) 0 51 #endif 52 45 53 /* ==== COMPILER() - primary detection of the compiler being used to build the project, in alphabetical order ==== */ 46 54 … … 49 57 #if defined(__clang__) 50 58 #define WTF_COMPILER_CLANG 1 51 #define WTF_COMPILER_SUPPORTS_BLOCKS __has_feature(blocks) 52 #define WTF_COMPILER_SUPPORTS_C_STATIC_ASSERT __has_feature(c_static_assert) 53 #define WTF_COMPILER_SUPPORTS_CXX_REFERENCE_QUALIFIED_FUNCTIONS __has_feature(cxx_reference_qualified_functions) 54 #define WTF_COMPILER_SUPPORTS_CXX_USER_LITERALS __has_feature(cxx_user_literals) 55 #define WTF_COMPILER_SUPPORTS_FALLTHROUGH_WARNINGS __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") 56 #define WTF_COMPILER_SUPPORTS_CXX_EXCEPTIONS __has_feature(cxx_exceptions) 59 #define WTF_COMPILER_SUPPORTS_BLOCKS COMPILER_HAS_CLANG_FEATURE(blocks) 60 #define WTF_COMPILER_SUPPORTS_C_STATIC_ASSERT COMPILER_HAS_CLANG_FEATURE(c_static_assert) 61 #define WTF_COMPILER_SUPPORTS_CXX_REFERENCE_QUALIFIED_FUNCTIONS COMPILER_HAS_CLANG_FEATURE(cxx_reference_qualified_functions) 62 #define WTF_COMPILER_SUPPORTS_CXX_USER_LITERALS COMPILER_HAS_CLANG_FEATURE(cxx_user_literals) 63 #define WTF_COMPILER_SUPPORTS_FALLTHROUGH_WARNINGS COMPILER_HAS_CLANG_FEATURE(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") 64 #define WTF_COMPILER_SUPPORTS_CXX_EXCEPTIONS COMPILER_HAS_CLANG_FEATURE(cxx_exceptions) 65 #define WTF_COMPILER_SUPPORTS_BUILTIN_IS_TRIVIALLY_COPYABLE COMPILER_HAS_CLANG_FEATURE(is_trivially_copyable) 57 66 58 67 #ifdef __cplusplus … … 136 145 #endif 137 146 138 #if defined(__has_feature) 139 #define ASAN_ENABLED __has_feature(address_sanitizer) 140 #else 141 #define ASAN_ENABLED 0 142 #endif 147 #define ASAN_ENABLED COMPILER_HAS_CLANG_FEATURE(address_sanitizer) 143 148 144 149 #if ASAN_ENABLED -
trunk/Source/WTF/wtf/StdLibExtras.h
r204992 r205066 29 29 30 30 #include <chrono> 31 #include <cstring> 31 32 #include <memory> 32 #include <string.h>33 33 #include <wtf/Assertions.h> 34 34 #include <wtf/CheckedArithmetic.h> 35 #include <wtf/Compiler.h> 35 36 36 37 // This was used to declare and define a static local variable (static T;) so that … … 146 147 { 147 148 static_assert(sizeof(FromType) == sizeof(ToType), "bitwise_cast size of FromType and ToType must be equal!"); 148 union { 149 FromType from; 150 ToType to; 151 } u; 152 u.from = from; 153 return u.to; 149 #if COMPILER_SUPPORTS(BUILTIN_IS_TRIVIALLY_COPYABLE) 150 // Not all recent STL implementations support the std::is_trivially_copyable type trait. Work around this by only checking on toolchains which have the equivalent compiler intrinsic. 151 static_assert(__is_trivially_copyable(ToType), "bitwise_cast of non-trivially-copyable type!"); 152 static_assert(__is_trivially_copyable(FromType), "bitwise_cast of non-trivially-copyable type!"); 153 #endif 154 ToType to; 155 std::memcpy(&to, &from, sizeof(to)); 156 return to; 154 157 } 155 158
Note: See TracChangeset
for help on using the changeset viewer.