From 32460dfc094f1469d3313dc61189bc3e0d02b7c9 Mon Sep 17 00:00:00 2001 From: ToyB-Chan Date: Mon, 8 Jun 2026 09:28:33 +0200 Subject: [PATCH] realloc and different heap validation types --- minimal_heap.c | 128 ++++++++++++++++++++++++++++++++++++++------ minimal_heap.h | 15 +++--- minimal_heap_test.c | 12 +++-- 3 files changed, 128 insertions(+), 27 deletions(-) diff --git a/minimal_heap.c b/minimal_heap.c index 16f21c9..ca5deec 100644 --- a/minimal_heap.c +++ b/minimal_heap.c @@ -156,7 +156,77 @@ void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size) void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize) { - return NULL; + if (newSize == 0) + { + MIHP_Free(heap, ptr); + return NULL; + } + + if (heap == NULL) + return NULL; + + if (ptr == NULL) + return MIHP_Allocate(heap, newSize); + + if (!MIHP_IsPointerInHeap(heap, ptr)) + return NULL; + + MIHP_LOCK_HEAP(&heap->HeapLock); + + size_t segmentHeaderSize = MIHP_GetHeapAlignedSize(heap, sizeof(MIHP_HeapSegmentHeader)); + MIHP_HeapSegmentHeader* segment = (MIHP_HeapSegmentHeader*)((char*)ptr - segmentHeaderSize); + MIHP_ValidateHeapSegmentHeader(heap, segment); + + if (newSize > segment->OccupiedSize) + { + size_t maxPayloadSize = segment->SegmentSize - segmentHeaderSize; + if (newSize <= maxPayloadSize) + { + MIHP_MEMSET((char*)ptr + segment->OccupiedSize, newSize - segment->OccupiedSize, heap->Config.AllocationInitialValue); + segment->OccupiedSize = newSize; + segment->Checksum = MIHP_GenerateHeapSegmentChecksum(segment); + + MIHP_UNLOCK_HEAP(&heap->HeapLock); + return ptr; + } + + if (segment->NextSegment && MIHP_MergeHeapSegments(segment, segment->NextSegment)) + { + MIHP_UNLOCK_HEAP(&heap->HeapLock); + return MIHP_Realloc(heap, ptr, newSize); + } + + MIHP_UNLOCK_HEAP(&heap->HeapLock); + + void* newPtr = MIHP_Allocate(heap, newSize); + if (!newPtr) + return NULL; + + for (size_t i = 0; i < segment->OccupiedSize; i++) + ((char*)newPtr)[i] = ((char*)ptr)[i]; + + MIHP_Free(heap, ptr); + return newPtr; + } + else if (newSize < segment->OccupiedSize) + { + segment->OccupiedSize = newSize; + segment->Checksum = MIHP_GenerateHeapSegmentChecksum(segment); + + size_t alignedNewSize = MIHP_GetHeapAlignedSize(heap, newSize); + size_t minimumPayloadSize = heap->Config.AllocationAlignment; + if (segment->SegmentSize > 2 * segmentHeaderSize + alignedNewSize + minimumPayloadSize) + { + size_t newSplitSegmentSize = segment->SegmentSize - segmentHeaderSize - alignedNewSize; + MIHP_SplitHeapSegment(segment, newSplitSegmentSize, NULL); + } + + MIHP_UNLOCK_HEAP(&heap->HeapLock); + return ptr; + } + + MIHP_UNLOCK_HEAP(&heap->HeapLock); + return ptr; } bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr) @@ -302,7 +372,9 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t { MIHP_ASSERT(heap); - size_t effectiveSize = ((requestedSize + MIHP_MINIMAL_MEMORY_AREA_SIZE - 1) / MIHP_MINIMAL_MEMORY_AREA_SIZE) * MIHP_MINIMAL_MEMORY_AREA_SIZE; + size_t effectiveSize = ((requestedSize + heap->Config.MinimalMemoryAreaSize - 1) / heap->Config.MinimalMemoryAreaSize) * heap->Config.MinimalMemoryAreaSize; + effectiveSize = MIHP_MAX(effectiveSize, heap->Config.MinimalMemoryAreaSize); + effectiveSize = MIHP_MIN(effectiveSize, heap->Config.MaximalMemoryAreaSize); MIHP_HeapMemoryAreaHeader* area = MIHP_PlatformRequestMemory(effectiveSize); if (area == NULL) @@ -358,6 +430,8 @@ MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* ar segment->Checksum = ~0; area->NumSegments++; + area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(area); + area->OwningHeap->Stats.NumTotalSegments++; return segment; @@ -464,37 +538,56 @@ uint32_t MIHP_HashMemoryRegion(const void* data, size_t size) uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_HeapMemoryAreaHeader* area) { -#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION + +#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE return 0; -#endif +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER + return 0xAADEADAA; +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM MIHP_ASSERT(area); // Do not include the checksum itself into the new checksum size_t size = offsetof(MIHP_HeapMemoryAreaHeader, Checksum); return MIHP_HashMemoryRegion(area, size); + +#else + #error "Invalid heap structure validation type" +#endif } uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment) { -#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION +#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE return 0; -#endif +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER + return 0x55DEAD55; +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM MIHP_ASSERT(segment); // Do not include the checksum itself into the new checksum size_t size = offsetof(MIHP_HeapSegmentHeader, Checksum); return MIHP_HashMemoryRegion(segment, size); + +#else + #error "Invalid heap structure validation type" +#endif } void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_HeapMemoryAreaHeader* area) { -#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION - return; -#endif + uint32_t newChecksum; - uint32_t newChecksum = MIHP_GenerateHeapMemoryAreaChecksum(area); +#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE + return; +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER + newChecksum = 0xAADEADAA; +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM + newChecksum = MIHP_GenerateHeapMemoryAreaChecksum(area); +#else + #error "Invalid heap structure validation type" +#endif if (area->Checksum != newChecksum) { @@ -511,11 +604,17 @@ void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_Hea void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSegmentHeader* segment) { -#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION - return; -#endif + uint32_t newChecksum; - uint32_t newChecksum = MIHP_GenerateHeapSegmentChecksum(segment); +#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE + return; +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER + newChecksum = 0x55DEAD55; +#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM + newChecksum = MIHP_GenerateHeapSegmentChecksum(segment); +#else + #error "Invalid heap structure validation type" +#endif if (segment->Checksum != newChecksum) { @@ -529,4 +628,3 @@ void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSe MIHP_PlatformOnHeapCorruptionDetected(corruptionInfo); } } - diff --git a/minimal_heap.h b/minimal_heap.h index d5b8bd9..a80037b 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -4,8 +4,11 @@ #include #include -#define MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION 1 -#define MIHP_USE_CANARY_VALIDATION 1 +#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE 0 +#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER 1 +#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM 2 + +#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM #define MIHP_HEAP_CORRUPTION_TYPE_MEMORY_AREA_CHECKSUM_MISMATCH 0 #define MIHP_HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH 1 @@ -80,13 +83,11 @@ void MIHP_PlatformOnHeapCorruptionDetected(MIHP_HeapCorruptionInfo info); /* === */ /* Defines to be configured by the library user */ -#define MIHP_MINIMAL_MEMORY_AREA_SIZE (4096 * 32) - #define MIHP_ASSERT(Condition) while(1) { if (Condition) break; *(volatile char*)(0x0) = 0; } -#define MIHP_HEAP_LOCK_TYPE uint8_t -#define MIHP_LOCK_HEAP(LockVariablePtr) {} -#define MIHP_UNLOCK_HEAP(LockVarialbePtr) {} +#define MIHP_HEAP_LOCK_TYPE uint8_t // Does NOT have to be reentred safe +#define MIHP_LOCK_HEAP(LockVarPtr) { while (*(LockVarPtr)) {}; *(LockVarPtr) = true; } +#define MIHP_UNLOCK_HEAP(LockVarPtr) { *(LockVarPtr) = false; } /* === */ typedef struct _MIHP_HeapInfo diff --git a/minimal_heap_test.c b/minimal_heap_test.c index fb0c76b..371329b 100644 --- a/minimal_heap_test.c +++ b/minimal_heap_test.c @@ -21,7 +21,7 @@ void MIHP_PlatformOnHeapCorruptionDetected(MIHP_HeapCorruptionInfo info) __debugbreak(); } -#define NUM_ALLOCATIONS (4096 * 32) +#define NUM_ALLOCATIONS (4096 * 4) void* myptrs[NUM_ALLOCATIONS] = { 0 }; @@ -67,15 +67,17 @@ int main() for (int i = 0; i < NUM_ALLOCATIONS; i++) { volatile int n = i; - if (!myptrs[i]) + if (myptrs[i]) { - size_t size = 541 + rand() % 2564; + size_t size = 300 + rand() % 500; #if USE_MALLOC - myptrs[i] = malloc(size); + myptrs[i] = realloc(myptrs[i], size); #else - myptrs[i] = MIHP_Allocate(myHeap, size); + myptrs[i] = MIHP_Realloc(myHeap, myptrs[i], size); MIHP_ValidateHeap(myHeap); + + #endif } }