From 07c59eda00841aafaafd8fd648217b56b1e907c9 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 21 Jun 2023 17:14:53 -0700 Subject: 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. --- src/support/allocators/secure.h | 36 +++++++++++++++---------------- src/support/allocators/zeroafterfree.h | 39 +++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h index b2076bea07..558f835f11 100644 --- a/src/support/allocators/secure.h +++ b/src/support/allocators/secure.h @@ -17,27 +17,14 @@ // out of memory and clears its contents before deletion. // template -struct secure_allocator : public std::allocator { - using base = std::allocator; - using traits = std::allocator_traits; - 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; - secure_allocator() noexcept {} - secure_allocator(const secure_allocator& a) noexcept : base(a) {} +struct secure_allocator { + using value_type = T; + + secure_allocator() = default; template - secure_allocator(const secure_allocator& a) noexcept : base(a) - { - } - ~secure_allocator() noexcept {} - template - struct rebind { - typedef secure_allocator other; - }; + secure_allocator(const secure_allocator&) noexcept {} - T* allocate(std::size_t n, const void* hint = nullptr) + T* allocate(std::size_t n) { T* allocation = static_cast(LockedPoolManager::Instance().alloc(sizeof(T) * n)); if (!allocation) { @@ -53,6 +40,17 @@ struct secure_allocator : public std::allocator { } LockedPoolManager::Instance().free(p); } + + template + friend bool operator==(const secure_allocator&, const secure_allocator&) noexcept + { + return true; + } + template + friend bool operator!=(const secure_allocator&, const secure_allocator&) noexcept + { + return false; + } }; // This is exactly like std::string, but with a custom allocator. 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 template -struct zero_after_free_allocator : public std::allocator { - using base = std::allocator; - using traits = std::allocator_traits; - 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 - zero_after_free_allocator(const zero_after_free_allocator& a) noexcept : base(a) + zero_after_free_allocator(const zero_after_free_allocator&) noexcept + { + } + + T* allocate(std::size_t n) { + return std::allocator{}.allocate(n); } - ~zero_after_free_allocator() noexcept {} - template - struct rebind { - typedef zero_after_free_allocator other; - }; void deallocate(T* p, std::size_t n) { if (p != nullptr) memory_cleanse(p, sizeof(T) * n); - std::allocator::deallocate(p, n); + std::allocator{}.deallocate(p, n); + } + + template + friend bool operator==(const zero_after_free_allocator&, const zero_after_free_allocator&) noexcept + { + return true; + } + template + friend bool operator!=(const zero_after_free_allocator&, const zero_after_free_allocator&) noexcept + { + return false; } }; -- cgit v1.2.3