diff options
author | Casey Carter <cacarter@microsoft.com> | 2023-06-21 17:14:53 -0700 |
---|---|---|
committer | Casey Carter <cacarter@microsoft.com> | 2023-07-24 22:33:40 -0700 |
commit | 07c59eda00841aafaafd8fd648217b56b1e907c9 (patch) | |
tree | 20b3614e414238378396a55083a27a52fd6f49b4 /src/support/allocators/zeroafterfree.h | |
parent | 6a473373d4953cabbb219eae8b709150a45796e6 (diff) | |
download | bitcoin-07c59eda00841aafaafd8fd648217b56b1e907c9.tar.xz |
Don't derive secure_allocator from std::allocator
Affects both secure_allocator and zero_after_free_allocator.
Giving the C++ Standard Committee control of the public interface of your type means they will break it. C++23 adds a new `allocate_at_least` member to `std::allocator`. Very bad things happen when, say, `std::vector` uses `allocate_at_least` from `secure_allocator`'s base to allocate memory which it then tries to free with `secure_allocator::deallocate`.
Drive-by: Aggressively remove facilities unnecessary since C++11 from both allocators to keep things simple.
Diffstat (limited to 'src/support/allocators/zeroafterfree.h')
-rw-r--r-- | src/support/allocators/zeroafterfree.h | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h index 2dc644c242..6d50eb70a6 100644 --- a/src/support/allocators/zeroafterfree.h +++ b/src/support/allocators/zeroafterfree.h @@ -12,31 +12,36 @@ #include <vector> template <typename T> -struct zero_after_free_allocator : public std::allocator<T> { - using base = std::allocator<T>; - using traits = std::allocator_traits<base>; - using size_type = typename traits::size_type; - using difference_type = typename traits::difference_type; - using pointer = typename traits::pointer; - using const_pointer = typename traits::const_pointer; - using value_type = typename traits::value_type; - zero_after_free_allocator() noexcept {} - zero_after_free_allocator(const zero_after_free_allocator& a) noexcept : base(a) {} +struct zero_after_free_allocator { + using value_type = T; + + zero_after_free_allocator() noexcept = default; template <typename U> - zero_after_free_allocator(const zero_after_free_allocator<U>& a) noexcept : base(a) + zero_after_free_allocator(const zero_after_free_allocator<U>&) noexcept + { + } + + T* allocate(std::size_t n) { + return std::allocator<T>{}.allocate(n); } - ~zero_after_free_allocator() noexcept {} - template <typename Other> - struct rebind { - typedef zero_after_free_allocator<Other> other; - }; void deallocate(T* p, std::size_t n) { if (p != nullptr) memory_cleanse(p, sizeof(T) * n); - std::allocator<T>::deallocate(p, n); + std::allocator<T>{}.deallocate(p, n); + } + + template <typename U> + friend bool operator==(const zero_after_free_allocator&, const zero_after_free_allocator<U>&) noexcept + { + return true; + } + template <typename U> + friend bool operator!=(const zero_after_free_allocator&, const zero_after_free_allocator<U>&) noexcept + { + return false; } }; |