21#include "lib/stdcompat/bit.h"
22#include "pw_allocator/block/contiguous.h"
23#include "pw_allocator/config.h"
25namespace pw::allocator {
52template <
typename Derived>
58 static_assert(is_contiguous_v<Derived>,
59 "Types derived from PoisonableBlock must also derive from "
64 static constexpr size_t kPoisonOffset = Derived::ReservedWhenFree();
68 return derived()->DoGetPoisonWord();
83 constexpr uintptr_t DoGetPoisonWord()
const {
85 return static_cast<uintptr_t
>(0xAD5bE10DDCCEFADEULL);
104 constexpr Derived* derived() {
return static_cast<Derived*
>(
this); }
105 constexpr const Derived* derived()
const {
106 return static_cast<const Derived*
>(
this);
111 constexpr uintptr_t* PoisonableBegin()
const {
112 auto addr = cpp20::bit_cast<uintptr_t>(derived()->UsableSpaceUnchecked());
113 addr =
AlignUp(addr + kPoisonOffset,
sizeof(uintptr_t*));
114 return cpp20::bit_cast<uintptr_t*>(addr);
119 constexpr uintptr_t* PoisonableEnd()
const {
120 auto addr = cpp20::bit_cast<uintptr_t>(derived()->UsableSpaceUnchecked());
122 AlignDown(addr + derived()->InnerSizeUnchecked(),
sizeof(uintptr_t*));
123 return cpp20::bit_cast<uintptr_t*>(addr);
128template <
typename BlockType>
129struct is_poisonable : std::is_base_of<internal::PoisonableBase, BlockType> {};
132template <
typename BlockType>
141void CheckPoisonedWhileInUse(
const void* block,
bool is_free);
145void CheckPoisonCorrupted(
const void* block,
bool pattern_is_intact);
151template <
typename Derived>
153 if constexpr (Hardening::kIncludesDebugChecks) {
154 derived()->CheckInvariants();
156 return derived()->IsPoisonedUnchecked();
159template <
typename Derived>
161 if constexpr (Hardening::kIncludesDebugChecks) {
162 derived()->CheckInvariants();
164 auto* begin = PoisonableBegin();
165 auto* end = PoisonableEnd();
167 std::fill(begin, end, derived()->GetPoisonWord());
168 derived()->SetPoisoned(
true);
170 if constexpr (Hardening::kIncludesDebugChecks) {
171 derived()->CheckInvariants();
175template <
typename Derived>
177 size_t new_inner_size) {
178 bool should_poison = derived()->IsPoisoned();
179 derived()->SetPoisoned(
false);
181 derived()->ContiguousBlock<Derived>::DoSplitFirst(new_inner_size);
183 trailing->SetPoisoned(
true);
188template <
typename Derived>
190 size_t new_inner_size) {
191 bool should_poison = derived()->IsPoisoned();
192 derived()->SetPoisoned(
false);
194 derived()->ContiguousBlock<Derived>::DoSplitLast(new_inner_size);
196 derived()->SetPoisoned(
true);
201template <
typename Derived>
204 derived()->SetPoisoned(
false);
205 derived()->ContiguousBlock<Derived>::DoMergeNext();
208template <
typename Derived>
210 if (!derived()->IsPoisonedUnchecked()) {
214 bool valid = derived()->IsFreeUnchecked();
215 if constexpr (Hardening::kIncludesDebugChecks) {
216 internal::CheckPoisonedWhileInUse(
this, valid || !strict);
219 auto* begin = PoisonableBegin();
220 auto* end = PoisonableEnd();
222 valid &= std::all_of(
223 begin, end, [
this](uintptr_t word) {
return word == GetPoisonWord(); });
225 if constexpr (Hardening::kIncludesDebugChecks) {
226 internal::CheckPoisonCorrupted(
this, valid || !strict);
232template <
typename Derived>
235 derived()->SetPoisoned(
false);
Definition: poisonable.h:53
constexpr void SetFree(bool is_free)
Clears the poisoned state if a block is not free.
Definition: poisonable.h:233
constexpr Derived * DoSplitLast(size_t new_inner_size)
Definition: poisonable.h:189
constexpr void DoMergeNext()
Definition: poisonable.h:202
constexpr bool DoCheckInvariants(bool strict) const
Like IsValid, but crashes if invalid.
Definition: poisonable.h:209
constexpr Derived * DoSplitFirst(size_t new_inner_size)
Definition: poisonable.h:176
constexpr void Poison()
Definition: poisonable.h:160
constexpr uintptr_t GetPoisonWord() const
Returns the value written to a block's usable space when poisoning.
Definition: poisonable.h:67
constexpr bool IsPoisoned() const
Returns whether this block has been poisoned.
Definition: poisonable.h:152
constexpr bool is_poisonable_v
Helper variable template for is_poisonable<BlockType>::value.
Definition: poisonable.h:133
constexpr size_t AlignUp(uintptr_t value, size_t alignment)
Returns the value rounded up to the nearest multiple of alignment.
Definition: alignment.h:54
constexpr size_t AlignDown(uintptr_t value, size_t alignment)
Returns the value rounded down to the nearest multiple of alignment.
Definition: alignment.h:41
Definition: poisonable.h:29
Trait type that allow interrogating a block as to whether it is poisonable.
Definition: poisonable.h:129