From f68b37b245784af487a18aa59356e5af80fe5504 Mon Sep 17 00:00:00 2001 From: ToyB-Chan Date: Mon, 8 Jun 2026 19:48:22 +0200 Subject: [PATCH 1/5] added double free fault --- minimal_heap.h | 3 +-- minimal_heap_implementation.inl | 10 ++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/minimal_heap.h b/minimal_heap.h index a89c758..8172c10 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -39,8 +39,7 @@ void MIHP_PlatformOnHeapCorruptionDetected(struct _MIHP_HeapCorruptionInfo info) #define MIHP_HEAP_CORRUPTION_TYPE_MEMORY_AREA_CHECKSUM_MISMATCH 0 #define MIHP_HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH 1 -#define MIHP_HEAP_CORRUPTION_TYPE_FRONT_CANARY_MISMATCH 2 -#define MIHP_HEAP_CORRUPTION_TYPE_REAR_CANARY_MISMATCH 3 +#define MIHP_HEAP_CORRUPTION_TYPE_DOUBLE_FREE 2 typedef struct _MIHP_HeapConfig { diff --git a/minimal_heap_implementation.inl b/minimal_heap_implementation.inl index 592935e..5eec40d 100644 --- a/minimal_heap_implementation.inl +++ b/minimal_heap_implementation.inl @@ -254,6 +254,16 @@ bool MIHP_Free(MIHP_Heap* heap, void* ptr) MIHP_HeapMemoryAreaHeader* area = segment->OwningMemoryArea; MIHP_ValidateHeapMemoryAreaHeader(heap, area); + if (segment->OccupiedSize == 0) + { + MIHP_HeapCorruptionInfo corruptionInfo = {0}; + corruptionInfo.Heap = heap; + corruptionInfo.Type = MIHP_HEAP_CORRUPTION_TYPE_DOUBLE_FREE; + corruptionInfo.Ptr = ptr; + + MIHP_PlatformOnHeapCorruptionDetected(corruptionInfo); + } + segment->OccupiedSize = 0; segment->Checksum = MIHP_GenerateHeapSegmentChecksum(segment); From af70cf0648c3280fd68f7f0ccb4d6bb8e730f1f7 Mon Sep 17 00:00:00 2001 From: ToyB-Chan Date: Mon, 8 Jun 2026 19:49:18 +0200 Subject: [PATCH 2/5] Update minimal_heap_implementation.inl --- minimal_heap_implementation.inl | 1 + 1 file changed, 1 insertion(+) diff --git a/minimal_heap_implementation.inl b/minimal_heap_implementation.inl index 5eec40d..97e0195 100644 --- a/minimal_heap_implementation.inl +++ b/minimal_heap_implementation.inl @@ -262,6 +262,7 @@ bool MIHP_Free(MIHP_Heap* heap, void* ptr) corruptionInfo.Ptr = ptr; MIHP_PlatformOnHeapCorruptionDetected(corruptionInfo); + return false; } segment->OccupiedSize = 0; From 57ce5af8e629156fa6badd6e7a1249300172ede0 Mon Sep 17 00:00:00 2001 From: ToyB-Chan Date: Mon, 8 Jun 2026 19:52:30 +0200 Subject: [PATCH 3/5] Update minimal_heap.h --- minimal_heap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minimal_heap.h b/minimal_heap.h index 8172c10..70ad352 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -25,7 +25,7 @@ #endif #ifndef MIHP_HEAP_LOCK_TYPE - #define MIHP_HEAP_LOCK_TYPE bool // Does NOT have to be reentred safe + #define MIHP_HEAP_LOCK_TYPE volatile bool // Does NOT have to be reentred safe #define MIHP_LOCK_HEAP(LockVarPtr) { while (*(LockVarPtr)) {}; *(LockVarPtr) = true; } #define MIHP_UNLOCK_HEAP(LockVarPtr) { *(LockVarPtr) = false; } #endif From d0e6bccafef6aedb796271c76c35614875fae849 Mon Sep 17 00:00:00 2001 From: ToyB-Chan Date: Mon, 8 Jun 2026 20:29:45 +0200 Subject: [PATCH 4/5] platform can now properly return larger amounts of memory as requested --- minimal_heap.h | 8 +++++--- minimal_heap_implementation.inl | 27 ++++++++++++++++----------- minimal_heap_test.c | 9 +++++---- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/minimal_heap.h b/minimal_heap.h index 70ad352..a3510e0 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -32,8 +32,8 @@ /* */ /* Hooks to be implemented by the library user */ -void* MIHP_PlatformRequestMemory(size_t size); // Alignment must at least be alignment of size_t -bool MIHP_PlatformFreeMemory(void* ptr, size_t size); +void* MIHP_PlatformRequestMemory(size_t minRequestedSize, size_t* outActualSize); // Alignment must at least be alignment of size_t, outActualSize must at least be minRequestedSize +bool MIHP_PlatformFreeMemory(void* ptr, size_t actualSize); void MIHP_PlatformOnHeapCorruptionDetected(struct _MIHP_HeapCorruptionInfo info); /* */ @@ -108,6 +108,8 @@ typedef struct _MIHP_Heap MIHP_HeapMemoryAreaHeader* FirstArea; MIHP_HeapMemoryAreaHeader* LastSuccessfulAllocationArea; + size_t HeapStructureAllocationSize; + MIHP_HEAP_LOCK_TYPE HeapLock; } MIHP_Heap; @@ -130,7 +132,7 @@ bool MIHP_DestroyHeapMemoryArea(MIHP_Heap* heap, MIHP_HeapMemoryAreaHeader* area MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* area, void* segmentStart, size_t size); bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment); -bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentSize, MIHP_HeapSegmentHeader** outNewSegment); +bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentSize, MIHP_HeapSegmentHeader** optOutNewSegment); bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegmentHeader* segmentToAbsorb); size_t MIHP_GetHeapAlignedSize(const MIHP_Heap* heap, size_t size); diff --git a/minimal_heap_implementation.inl b/minimal_heap_implementation.inl index 97e0195..df69f37 100644 --- a/minimal_heap_implementation.inl +++ b/minimal_heap_implementation.inl @@ -19,19 +19,22 @@ MIHP_Heap* MIHP_CreateHeap(MIHP_HeapConfig config) if (config.MaximalMemoryAreaSize % config.AllocationAlignment != 0) return NULL; - MIHP_Heap* heap = (MIHP_Heap*)MIHP_PlatformRequestMemory(sizeof(MIHP_Heap)); + size_t actualHeapStructAllocSize = 0; + MIHP_Heap* heap = (MIHP_Heap*)MIHP_PlatformRequestMemory(sizeof(MIHP_Heap), &actualHeapStructAllocSize); if (heap == NULL) return NULL; + MIHP_ASSERT(actualHeapStructAllocSize >= sizeof(MIHP_Heap)); MIHP_MEMSET(heap, sizeof(MIHP_Heap), 0); heap->Config = config; - - heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, config.MinimalMemoryAreaSize); + heap->HeapStructureAllocationSize = actualHeapStructAllocSize; + heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, actualHeapStructAllocSize); heap->LastSuccessfulAllocationArea = heap->FirstArea; + if (heap->FirstArea == NULL) { - MIHP_PlatformFreeMemory(heap, sizeof(MIHP_Heap)); + MIHP_PlatformFreeMemory(heap, heap->HeapStructureAllocationSize); return NULL; } @@ -58,7 +61,7 @@ bool MIHP_DestroyHeap(MIHP_Heap* heap, bool force) MIHP_DestroyHeapMemoryArea(heap, currentArea); } - MIHP_PlatformFreeMemory(heap, sizeof(MIHP_Heap)); + MIHP_PlatformFreeMemory(heap, heap->HeapStructureAllocationSize); return true; } @@ -389,13 +392,15 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t req effectiveSize = MIHP_MAX(effectiveSize, heap->Config.MinimalMemoryAreaSize); effectiveSize = MIHP_MIN(effectiveSize, heap->Config.MaximalMemoryAreaSize); - MIHP_HeapMemoryAreaHeader* area = (MIHP_HeapMemoryAreaHeader*)MIHP_PlatformRequestMemory(effectiveSize); + size_t actualSize = 0; + MIHP_HeapMemoryAreaHeader* area = (MIHP_HeapMemoryAreaHeader*)MIHP_PlatformRequestMemory(effectiveSize, &actualSize); if (area == NULL) return NULL; + MIHP_ASSERT(actualSize >= effectiveSize); MIHP_MEMSET(area, sizeof(MIHP_HeapMemoryAreaHeader), 0); - area->AreaSize = effectiveSize; + area->AreaSize = actualSize; area->OwningHeap = heap; area->Checksum = ~0; @@ -404,7 +409,7 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t req area->FirstSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(area->FirstSegment); heap->Stats.NumMemoryAreas++; - heap->Stats.TotalSize += effectiveSize; + heap->Stats.TotalSize += area->AreaSize; return area; } @@ -466,7 +471,7 @@ bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment) return true; } -bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentMinSize, MIHP_HeapSegmentHeader** outNewSegment) +bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentMinSize, MIHP_HeapSegmentHeader** optOutNewSegment) { MIHP_ASSERT(sourceSegment); @@ -496,8 +501,8 @@ bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegm sourceSegment->NextSegment = newSegment; - if (outNewSegment) - *outNewSegment = newSegment; + if (optOutNewSegment) + *optOutNewSegment = newSegment; newSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(newSegment); sourceSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(sourceSegment); diff --git a/minimal_heap_test.c b/minimal_heap_test.c index 4c194d0..421f21e 100644 --- a/minimal_heap_test.c +++ b/minimal_heap_test.c @@ -7,14 +7,15 @@ #define USE_MALLOC 0 -//#define MIHP_ValidateHeap() +#define MIHP_ValidateHeap() -void* MIHP_PlatformRequestMemory(size_t size) +void* MIHP_PlatformRequestMemory(size_t minRequestedSize, size_t* outActualSize) { - return malloc(size); + *outActualSize = minRequestedSize; + return malloc(minRequestedSize); } -bool MIHP_PlatformFreeMemory(void* ptr, size_t size) +bool MIHP_PlatformFreeMemory(void* ptr, size_t actualSize) { free(ptr); return true; From db8f9f69ae8699158fa719ad19b4a89c5011d80d Mon Sep 17 00:00:00 2001 From: ToyB-Chan Date: Mon, 8 Jun 2026 20:30:08 +0200 Subject: [PATCH 5/5] warning fix --- minimal_heap_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minimal_heap_test.c b/minimal_heap_test.c index 421f21e..d8405cb 100644 --- a/minimal_heap_test.c +++ b/minimal_heap_test.c @@ -7,7 +7,7 @@ #define USE_MALLOC 0 -#define MIHP_ValidateHeap() +#define MIHP_ValidateHeap(x) void* MIHP_PlatformRequestMemory(size_t minRequestedSize, size_t* outActualSize) {