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 "mm/page_frame.h"
#include "utils/math.h" #include "utils/math.h"
#include "utils/logger.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) { void heap_segment_init(heap_segment_T* segment, heap_segment_T* next, heap_segment_T* prev, uint64_t size) {
segment->magic = HEAP_SEGMENT_MAGIC; segment->magic = HEAP_SEGMENT_MAGIC;
@ -18,7 +19,7 @@ bool heap_segment_validate(heap_segment_T* segment) {
return segment->magic == HEAP_SEGMENT_MAGIC; 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->prev == NULL) { return false; }
if (!segment->free || !segment->prev->free) { 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; segment->next->prev = segment->prev;
} }
if (segment == heap->last_segment) {
heap->last_segment = segment->prev;
}
// fuse with previous segment // fuse with previous segment
segment->prev->size += sizeof(heap_segment_T) + segment->size; segment->prev->size += sizeof(heap_segment_T) + segment->size;
@ -36,10 +41,10 @@ bool heap_segment_combine_prev(heap_segment_T* segment) {
return true; 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; } 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) { 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; new_segment->prev = segment;
// try to combine the new segment with the segment that comes after it // 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) { if (segment == heap->last_segment) {
heap->last_segment = new_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_segment_init(segment, NULL, heap->last_segment, size - sizeof(heap_segment_T));
heap->last_segment->next = segment; heap->last_segment->next = segment;
if (heap_segment_combine_prev(segment)) { if (heap_segment_combine_prev(heap, segment)) {
segment = heap->last_segment; segment = heap->last_segment;
} else { } else {
heap->last_segment = segment; heap->last_segment = segment;
@ -116,7 +121,8 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) {
heap_segment_T* segment = heap->start; heap_segment_T* segment = heap->start;
while (segment != NULL) { while (segment != NULL) {
if (!heap_segment_validate(segment)) { 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; return NULL;
} }
@ -130,7 +136,7 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) {
} }
segment->free = false; 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); segment = heap_append_segment(heap, size);
@ -139,39 +145,51 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) {
} }
segment->free = false; 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) { void heap_dump_segments(heap_T* heap) {
log(LOG_DEBUG, "<=====[ Dumping Heap Segments ]=====>"); log(LOG_DEBUG, "<=====[ Dumping Heap Segments ]=====>");
log(LOG_NONE, " |-------------------------|"); log(LOG_NONE, " |--------------------------|");
log(LOG_NONE, " | START |"); log(LOG_NONE, " | START |");
log(LOG_NONE, " | 0x%x |", heap->start); log(LOG_NONE, " | 0x%x |", heap->start);
log(LOG_NONE, " |------------v------------|"); log(LOG_NONE, " |-------------v------------|");
heap_segment_T* segment = heap->start; heap_segment_T* segment = heap->start;
while (segment != NULL) { while (segment != NULL) {
log(LOG_NONE, " |"); if (segment->magic != HEAP_SEGMENT_MAGIC) {
log(LOG_NONE, " |"); 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, " ! !!! Heap corrupted !!! !");
log(LOG_NONE, " | 0x%x |", (uint64_t)segment); log(LOG_NONE, " !~~~~~~~~~~~~~~~~~~~~~~~~~~!");
log(LOG_NONE, " | Valid: %? |", heap_segment_validate(segment)); memory_hexdump(segment, sizeof(heap_segment_T));
log(LOG_NONE, " | Free: %? |", segment->free); return;
log(LOG_NONE, " | Size: 0x%xd |", segment->size); }
log(LOG_NONE, " |------------v------------|");
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; segment = segment->next;
} }
log(LOG_NONE, " |"); log(LOG_NONE, " |");
log(LOG_NONE, " |"); log(LOG_NONE, " |");
log(LOG_NONE, " |------------^------------|"); log(LOG_NONE, " |-------------^------------|");
log(LOG_NONE, " | END |"); log(LOG_NONE, " | END |");
log(LOG_NONE, " | 0x%x |", heap->end); log(LOG_NONE, " | 0x%x |", heap->end);
log(LOG_NONE, " |-------------------------|"); log(LOG_NONE, " |--------------------------|");
} }
void heap_memory_free(heap_T* heap, void* address) { 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; segment->free = true;
// try to combine in both directions, so we don't splitter the heap in a ton of small segments // 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_prev(heap, segment);
heap_segment_combine_next(segment); heap_segment_combine_next(heap, segment);
} }