aboutsummaryrefslogtreecommitdiff
path: root/src/prevector.h
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@protonmail.com>2020-02-12 17:48:22 +0100
committerWladimir J. van der Laan <laanwj@protonmail.com>2020-02-12 17:48:30 +0100
commit2bdc476d4d23256d8396bb9051a511f540d87392 (patch)
tree0c53a9b7c3b0522801db923d85c52876f3940f40 /src/prevector.h
parentd4fc9aeb8b6a66d8d40ab93547c8b1390458d638 (diff)
parent5f26855f109af53a336d5f98ed0ae584e7a31f84 (diff)
downloadbitcoin-2bdc476d4d23256d8396bb9051a511f540d87392.tar.xz
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
Diffstat (limited to 'src/prevector.h')
-rw-r--r--src/prevector.h14
1 files changed, 9 insertions, 5 deletions
diff --git a/src/prevector.h b/src/prevector.h
index f4ece738a8..09debedc4f 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -15,7 +15,6 @@
#include <type_traits>
#include <utility>
-#pragma pack(push, 1)
/** Implements a drop-in replacement for std::vector<T> 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.
@@ -147,14 +146,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<T*>(_union.direct) + pos; }
const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
@@ -523,6 +528,5 @@ public:
return item_ptr(0);
}
};
-#pragma pack(pop)
#endif // BITCOIN_PREVECTOR_H