From abf22ba917e212fbd7ba572d92e3840177b26762 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Fri, 19 May 2023 01:20:15 +0200 Subject: [PATCH] fix (heap): fixed bug that caused invalid addresses as result of memory allocations --- src/mm/heap.c | 78 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/src/mm/heap.c b/src/mm/heap.c index f45758c..0887fe6 100644 --- a/src/mm/heap.c +++ b/src/mm/heap.c @@ -5,6 +5,7 @@ #include "mm/page_frame.h" #include "utils/math.h" #include "utils/logger.h" +#include "utils/memory.h" void heap_segment_init(heap_segment_T* segment, heap_segment_T* next, heap_segment_T* prev, uint64_t size) { segment->magic = HEAP_SEGMENT_MAGIC; @@ -18,7 +19,7 @@ bool heap_segment_validate(heap_segment_T* segment) { return segment->magic == HEAP_SEGMENT_MAGIC; } -bool heap_segment_combine_prev(heap_segment_T* segment) { +bool heap_segment_combine_prev(heap_T* heap, heap_segment_T* segment) { if (segment->prev == NULL) { return false; } if (!segment->free || !segment->prev->free) { return false; } @@ -28,6 +29,10 @@ bool heap_segment_combine_prev(heap_segment_T* segment) { segment->next->prev = segment->prev; } + if (segment == heap->last_segment) { + heap->last_segment = segment->prev; + } + // fuse with previous segment segment->prev->size += sizeof(heap_segment_T) + segment->size; @@ -36,10 +41,10 @@ bool heap_segment_combine_prev(heap_segment_T* segment) { return true; } -bool heap_segment_combine_next(heap_segment_T* segment) { +bool heap_segment_combine_next(heap_T* heap, heap_segment_T* segment) { if (segment->next == NULL) { return false; } - return heap_segment_combine_prev(segment->next); + return heap_segment_combine_prev(heap, segment->next); } bool heap_segment_shrink(heap_T* heap, heap_segment_T* segment, uint64_t size) { @@ -59,7 +64,7 @@ bool heap_segment_shrink(heap_T* heap, heap_segment_T* segment, uint64_t size) { new_segment->prev = segment; // try to combine the new segment with the segment that comes after it - heap_segment_combine_next(new_segment); + heap_segment_combine_next(heap, new_segment); if (segment == heap->last_segment) { heap->last_segment = new_segment; @@ -98,7 +103,7 @@ heap_segment_T* heap_append_segment(heap_T* heap, uint64_t minimum_size) { heap_segment_init(segment, NULL, heap->last_segment, size - sizeof(heap_segment_T)); heap->last_segment->next = segment; - if (heap_segment_combine_prev(segment)) { + if (heap_segment_combine_prev(heap, segment)) { segment = heap->last_segment; } else { heap->last_segment = segment; @@ -116,7 +121,8 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) { heap_segment_T* segment = heap->start; while (segment != NULL) { if (!heap_segment_validate(segment)) { - log(LOG_ERROR, "Heap Segment Invalid! while trying to allocate memory"); + log(LOG_ERROR, "Heap Segment (0x%x) Invalid! while trying to allocate memory", segment); + heap_dump_segments(heap); return NULL; } @@ -130,7 +136,7 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) { } segment->free = false; - return (heap_segment_T*)((uint64_t)segment + sizeof(heap_segment_T)); + return (void*)((uint64_t)segment + sizeof(heap_segment_T)); } segment = heap_append_segment(heap, size); @@ -139,39 +145,51 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) { } segment->free = false; - return (heap_segment_T*)((uint64_t)segment + sizeof(heap_segment_T)); + return (void*)((uint64_t)segment + sizeof(heap_segment_T)); } void heap_dump_segments(heap_T* heap) { log(LOG_DEBUG, "<=====[ Dumping Heap Segments ]=====>"); - log(LOG_NONE, " |-------------------------|"); - log(LOG_NONE, " | START |"); - log(LOG_NONE, " | 0x%x |", heap->start); - log(LOG_NONE, " |------------v------------|"); + log(LOG_NONE, " |--------------------------|"); + log(LOG_NONE, " | START |"); + log(LOG_NONE, " | 0x%x |", heap->start); + log(LOG_NONE, " |-------------v------------|"); heap_segment_T* segment = heap->start; while (segment != NULL) { - log(LOG_NONE, " |"); - log(LOG_NONE, " |"); - log(LOG_NONE, " |------------^------------|"); - log(LOG_NONE, " | Header (size: 0x%xw) |", sizeof(heap_segment_T)); - log(LOG_NONE, " |-------------------------|"); - log(LOG_NONE, " | 0x%x |", (uint64_t)segment); - log(LOG_NONE, " | Valid: %? |", heap_segment_validate(segment)); - log(LOG_NONE, " | Free: %? |", segment->free); - log(LOG_NONE, " | Size: 0x%xd |", segment->size); - log(LOG_NONE, " |------------v------------|"); + if (segment->magic != HEAP_SEGMENT_MAGIC) { + log(LOG_NONE, " |"); + log(LOG_NONE, " |"); + log(LOG_NONE, " !~~~~~~~~~~~~~^~~~~~~~~~~~~!"); + log(LOG_NONE, " ! !!! Heap corrupted !!! !"); + log(LOG_NONE, " !~~~~~~~~~~~~~~~~~~~~~~~~~~!"); + memory_hexdump(segment, sizeof(heap_segment_T)); + return; + } + + log(LOG_NONE, " |"); + log(LOG_NONE, " |"); + log(LOG_NONE, " |-------------^------------|"); + log(LOG_NONE, " | Header (size: 0x%xw) |", sizeof(heap_segment_T)); + log(LOG_NONE, " |--------------------------|"); + log(LOG_NONE, " | 0x%x |", (uint64_t)segment); + log(LOG_NONE, " | Valid: %? |", heap_segment_validate(segment)); + log(LOG_NONE, " | Free: %? |", segment->free); + log(LOG_NONE, " | Size: 0x%xd |", segment->size); + log(LOG_NONE, " | Prev: 0x%x |", (uint64_t)segment->prev); + log(LOG_NONE, " | Next: 0x%x |", (uint64_t)segment->next); + log(LOG_NONE, " |-------------v------------|"); segment = segment->next; } - log(LOG_NONE, " |"); - log(LOG_NONE, " |"); - log(LOG_NONE, " |------------^------------|"); - log(LOG_NONE, " | END |"); - log(LOG_NONE, " | 0x%x |", heap->end); - log(LOG_NONE, " |-------------------------|"); + log(LOG_NONE, " |"); + log(LOG_NONE, " |"); + log(LOG_NONE, " |-------------^------------|"); + log(LOG_NONE, " | END |"); + log(LOG_NONE, " | 0x%x |", heap->end); + log(LOG_NONE, " |--------------------------|"); } void heap_memory_free(heap_T* heap, void* address) { @@ -185,8 +203,8 @@ void heap_memory_free(heap_T* heap, void* address) { segment->free = true; // try to combine in both directions, so we don't splitter the heap in a ton of small segments - heap_segment_combine_prev(segment); - heap_segment_combine_next(segment); + heap_segment_combine_prev(heap, segment); + heap_segment_combine_next(heap, segment); }