luna/Heap: Scrub reallocations properly

This commit is contained in:
apio 2023-01-16 19:50:35 +01:00
parent 1b807a4e06
commit 329e8ab182
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 19 additions and 8 deletions

View File

@ -49,5 +49,7 @@ static_assert(get_blocks_from_size(0, 256) == 0);
// arithmetic.
template <typename T, typename Offset> constexpr T* offset_ptr(T* ptr, Offset offset)
{
// FIXME: The C standard does not mandate that char be 1 byte. This function (and probably many others) rely on that
// assumption.
return (T*)((char*)ptr + offset);
}

View File

@ -27,8 +27,8 @@ static constexpr int BLOCK_END_MEM = 1 << 2;
static constexpr usize BLOCK_MAGIC = 0x6d616c6c6f63210a; // echo 'malloc!' | hexdump -C (includes a newline)
static constexpr usize BLOCK_DEAD = 0xdeaddeaddeaddead;
static constexpr u8 KMALLOC_SCRUB_BYTE = 0xac;
static constexpr u8 KFREE_SCRUB_BYTE = 0xde;
static constexpr u8 MALLOC_SCRUB_BYTE = 0xac;
static constexpr u8 FREE_SCRUB_BYTE = 0xde;
static constexpr usize MINIMUM_PAGES_PER_ALLOCATION = 4;
@ -221,7 +221,7 @@ Result<void*> malloc_impl(usize size, bool should_scrub)
current->req_size = size;
current->status |= BLOCK_USED;
if (should_scrub) { memset(get_pointer_from_heap_block(current), KMALLOC_SCRUB_BYTE, size); }
if (should_scrub) { memset(get_pointer_from_heap_block(current), MALLOC_SCRUB_BYTE, size); }
return get_pointer_from_heap_block(current);
}
@ -237,7 +237,7 @@ Result<void> free_impl(void* ptr)
{
if (block->magic == BLOCK_DEAD) { dbgln("ERROR: Attempt to free memory at %p, which was already freed", ptr); }
else
dbgln("ERROR: Attempt to free memory at %p, which wasn't allocated with kmalloc", ptr);
dbgln("ERROR: Attempt to free memory at %p, which wasn't allocated with malloc", ptr);
return err(EFAULT);
}
@ -250,7 +250,7 @@ Result<void> free_impl(void* ptr)
else
block->status &= ~BLOCK_USED;
memset(ptr, KFREE_SCRUB_BYTE, block->req_size);
memset(ptr, FREE_SCRUB_BYTE, block->req_size);
auto maybe_next = heap.next(block);
if (maybe_next.has_value() && is_block_free(maybe_next.value()))
@ -295,7 +295,7 @@ Result<void*> realloc_impl(void* ptr, usize size)
dbgln("ERROR: Attempt to realloc memory at %p, which was already freed", ptr);
}
else
dbgln("ERROR: Attempt to realloc memory at %p, which wasn't allocated with kmalloc", ptr);
dbgln("ERROR: Attempt to realloc memory at %p, which wasn't allocated with malloc", ptr);
return err(EFAULT);
}
@ -311,7 +311,16 @@ Result<void*> realloc_impl(void* ptr, usize size)
if (block->full_size >= size)
{
// This block is already large enough!
// FIXME: Scrub this if necessary.
if (size > block->req_size)
{
// If the new size is larger, scrub the newly allocated space.
memset(offset_ptr(ptr, block->req_size), MALLOC_SCRUB_BYTE, size - block->req_size);
}
else if (size < block->req_size)
{
// If the new size is smaller, scrub the removed space as if it was freed.
memset(offset_ptr(ptr, size), FREE_SCRUB_BYTE, block->req_size - size);
}
block->req_size = size;
return ptr;
}
@ -322,7 +331,7 @@ Result<void*> realloc_impl(void* ptr, usize size)
memcpy(new_ptr, ptr, old_size > size ? size : old_size);
TRY(free_impl(ptr));
if (old_size < size) { memset(offset_ptr(new_ptr, old_size), KMALLOC_SCRUB_BYTE, size - old_size); }
if (old_size < size) { memset(offset_ptr(new_ptr, old_size), MALLOC_SCRUB_BYTE, size - old_size); }
return new_ptr;
}