From 56a75722c95cd4ed8ace2d5f6a84754e29cb1fa7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 12 Feb 2020 17:48:22 +0100 Subject: [PATCH] Merge #17708: prevector: avoid misaligned member accesses 5f26855f109af53a336d5f98ed0ae584e7a31f84 test: Remove ubsan alignment suppressions (Wladimir J. van der Laan) 9d933ef9191417b4b7d29eaa3c3a571f814acc8e prevector: avoid misaligned member accesses (Anthony Towns) Pull request description: Ensure prevector data is appropriately aligned. Earlier discussion in #17530. **Edit laanwj**: In contrast to #17530, it does this without increase in size of any of the coin cache data structures (x86_64, clang) | Struct | (size,align) before | (size,align) after | | ------------- | ------------- | ------- | | Coin | 48, 8 | 48, 8 | | CCoinsCacheEntry | 56, 8 | 56, 8 | | CScript | 32, 1 | 32, 8 | ACKs for top commit: laanwj: ACK 5f26855f109af53a336d5f98ed0ae584e7a31f84 practicalswift: ACK 5f26855f109af53a336d5f98ed0ae584e7a31f84 jonatack: ACK 5f26855f109af53a336d5f98ed0ae584e7a31f84 Tree-SHA512: 98d112d6856f683d5b212410b73f3071d2994f1efb046a2418a35890aa1cf1aa7c96a960fc2e963fa15241e861093c1ea41951cf5b4b5431f88345eb1dd0a98a --- src/prevector.h | 15 +++++++++------ test/sanitizer_suppressions/ubsan | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 133930ed4b..aeaf66b265 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -17,7 +17,6 @@ #include -#pragma pack(push, 1) /** Implements a drop-in replacement for std::vector which stores up to N * elements directly (without heap allocation). The types Size and Diff are * used to store element counts, and can be any unsigned + signed type. @@ -149,14 +148,20 @@ public: }; private: - size_type _size = 0; +#pragma pack(push, 1) union direct_or_indirect { char direct[sizeof(T) * N]; struct { - size_type capacity; char* indirect; + size_type capacity; }; - } _union = {}; + }; +#pragma pack(pop) + alignas(char*) direct_or_indirect _union = {}; + size_type _size = 0; + + static_assert(alignof(char*) % alignof(size_type) == 0 && sizeof(char*) % alignof(size_type) == 0, "size_type cannot have more restrictive alignment requirement than pointer"); + static_assert(alignof(char*) % alignof(T) == 0, "value_type T cannot have more restrictive alignment requirement than pointer"); T* direct_ptr(difference_type pos) { return reinterpret_cast(_union.direct) + pos; } const T* direct_ptr(difference_type pos) const { return reinterpret_cast(_union.direct) + pos; } @@ -567,6 +572,4 @@ public: } }; -#pragma pack(pop) - #endif // BITCOIN_PREVECTOR_H diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index d55119b266..baa213f768 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -1,5 +1,5 @@ -alignment:move.h -alignment:prevector.h +# -fsanitize=undefined suppressions +# ================================= bool:wallet/wallet.cpp float-divide-by-zero:policy/fees.cpp float-divide-by-zero:validation.cpp