From 329e8ab182de10d8279fbc98ac638bb2a78c581c Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 16 Jan 2023 19:50:35 +0100 Subject: [PATCH] luna/Heap: Scrub reallocations properly --- luna/include/luna/Alignment.h | 2 ++ luna/src/Heap.cpp | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/luna/include/luna/Alignment.h b/luna/include/luna/Alignment.h index af572950..4085e3ef 100644 --- a/luna/include/luna/Alignment.h +++ b/luna/include/luna/Alignment.h @@ -49,5 +49,7 @@ static_assert(get_blocks_from_size(0, 256) == 0); // arithmetic. template 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); } diff --git a/luna/src/Heap.cpp b/luna/src/Heap.cpp index f7839c12..2e9b686f 100644 --- a/luna/src/Heap.cpp +++ b/luna/src/Heap.cpp @@ -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 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 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 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 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 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 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; }