mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
prevector: avoid misaligned member accesses
`#pragma pack(1)` prevents aligning the struct and its members to their required alignment. This can result in code that performs non-aligned reads and writes to integers and pointers, which is problematic on some architectures. It also triggers UBsan — see https://github.com/bitcoin/bitcoin/pull/17156#issuecomment-543123631 and #17510.
This commit is contained in:
parent
1189b6acab
commit
9d933ef919
1 changed files with 9 additions and 5 deletions
|
@ -15,7 +15,6 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
/** Implements a drop-in replacement for std::vector<T> which stores up to N
|
/** 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
|
* elements directly (without heap allocation). The types Size and Diff are
|
||||||
* used to store element counts, and can be any unsigned + signed type.
|
* used to store element counts, and can be any unsigned + signed type.
|
||||||
|
@ -147,14 +146,20 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_type _size = 0;
|
#pragma pack(push, 1)
|
||||||
union direct_or_indirect {
|
union direct_or_indirect {
|
||||||
char direct[sizeof(T) * N];
|
char direct[sizeof(T) * N];
|
||||||
struct {
|
struct {
|
||||||
size_type capacity;
|
|
||||||
char* indirect;
|
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; }
|
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; }
|
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);
|
return item_ptr(0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#endif // BITCOIN_PREVECTOR_H
|
#endif // BITCOIN_PREVECTOR_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue