fix (heap): fixed bug that caused invalid addresses as result of memory allocations

This commit is contained in:
antifallobst 2023-05-19 01:20:15 +02:00
parent 9a35aa6648
commit abf22ba917
1 changed files with 48 additions and 30 deletions

View File

@ -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, " |--------------------------|");
log(LOG_NONE, " | START |");
log(LOG_NONE, " | 0x%x |", heap->start);
log(LOG_NONE, " |------------v------------|");
log(LOG_NONE, " |-------------v------------|");
heap_segment_T* segment = heap->start;
while (segment != NULL) {
if (segment->magic != HEAP_SEGMENT_MAGIC) {
log(LOG_NONE, " |");
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, " |--------------------------|");
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------------|");
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, " |-------------^------------|");
log(LOG_NONE, " | END |");
log(LOG_NONE, " | 0x%x |", heap->end);
log(LOG_NONE, " |-------------------------|");
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);
}