Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 39 additions & 7 deletions sdk/core/allocator/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,28 @@ __cheri_no_subobject_bounds MChunkHeader
bool isSealedObject : 1;
bool isPrevInUse : 1;
bool isCurrInUse : 1;

/**
* The type used for encoding an absolute offset into the heap as the
* optional first claimant of this object.
*/
enum class ClaimChain : ptraddr_t
{
/**
* The end of a claim chain, representing no further objects.
*
* The value 0 would, if interpreted literally, refer to the MSpace
* metadata at the top of the heap, and so cannot also be a claim
* object. It is therefore a good choice for the list terminator.
*/
None = 0,
};

/// Actual bit-width of a claims chain pointer
static constexpr size_t ClaimChainWidth = 16;

/// Head of a linked list of claims on this allocation
uint16_t claims;
ClaimChain claims : ClaimChainWidth;

__always_inline auto cell_prev()
{
Expand Down Expand Up @@ -485,7 +505,7 @@ __cheri_no_subobject_bounds MChunkHeader
{
Debug::Assert(previous->cell_next() == this,
"Unsplitting MChunkHeader into bad predecessor");
Debug::Assert(this->claims == 0,
Debug::Assert(this->claims == MChunkHeader::ClaimChain::None,
"Unsplitting MChunkHeader with active claims");

/*
Expand Down Expand Up @@ -537,10 +557,6 @@ __cheri_no_subobject_bounds MChunkHeader
};
static_assert(sizeof(MChunkHeader) == 8);
static_assert(std::is_standard_layout_v<MChunkHeader>);
static_assert(
offsetof(MChunkHeader, claims) == 2 * sizeof(SmallSize) + sizeof(uint16_t),
"Metadata is no longer 16 bits. Update the OwnerIDWidth constant to correct "
"the space used for the owner ID to match the remaining space.");

// the maximum requested size that is still categorised as a small bin
constexpr size_t MaxSmallRequest = MaxSmallSize - sizeof(MChunkHeader);
Expand Down Expand Up @@ -1000,6 +1016,18 @@ class MState
return cap;
}

/**
* Rederive a capability to a `T` from the heap range by relative offset.
* This does not apply bounds to the result.
*/
template<typename T>
T *rederive_relative(ptraddr_t address)
{
CHERI::Capability<T> cap{heapStart.cast<T>()};
cap.address() += address;
return cap;
}

// Returns the smallbin head for index i.
auto smallbin_at(BIndex i)
{
Expand Down Expand Up @@ -1373,7 +1401,7 @@ class MState
Capability heap{heapStart};
heap.address() = ptr.address();
auto chunk = MChunkHeader::from_body(heap);
if (chunk->claims > 0)
if (chunk->claims != MChunkHeader::ClaimChain::None)
{
/*
* The chunk was freed but ended up in
Expand Down Expand Up @@ -1410,6 +1438,10 @@ class MState
// capability.
Capability mem{chunk.body()};

Debug::Assert(
(bodySize + sizeof(MChunkHeader)) <= chunk.size_get(),
"mspace_free with claimed body that would exceeed chunk size");

bool isDoubleFree = false;

if (__predict_false(skipHazardCheck))
Expand Down
Loading
Loading