mirror of
https://github.com/ToyB-Chan/minimal-heap.git
synced 2026-07-13 21:51:16 +02:00
realloc and different heap validation types
This commit is contained in:
126
minimal_heap.c
126
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)
|
void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize)
|
||||||
{
|
{
|
||||||
|
if (newSize == 0)
|
||||||
|
{
|
||||||
|
MIHP_Free(heap, ptr);
|
||||||
return NULL;
|
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)
|
bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr)
|
||||||
@@ -302,7 +372,9 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t
|
|||||||
{
|
{
|
||||||
MIHP_ASSERT(heap);
|
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);
|
MIHP_HeapMemoryAreaHeader* area = MIHP_PlatformRequestMemory(effectiveSize);
|
||||||
if (area == NULL)
|
if (area == NULL)
|
||||||
@@ -358,6 +430,8 @@ MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* ar
|
|||||||
segment->Checksum = ~0;
|
segment->Checksum = ~0;
|
||||||
|
|
||||||
area->NumSegments++;
|
area->NumSegments++;
|
||||||
|
area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(area);
|
||||||
|
|
||||||
area->OwningHeap->Stats.NumTotalSegments++;
|
area->OwningHeap->Stats.NumTotalSegments++;
|
||||||
|
|
||||||
return segment;
|
return segment;
|
||||||
@@ -464,37 +538,56 @@ uint32_t MIHP_HashMemoryRegion(const void* data, size_t size)
|
|||||||
|
|
||||||
uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_HeapMemoryAreaHeader* area)
|
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;
|
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);
|
MIHP_ASSERT(area);
|
||||||
|
|
||||||
// Do not include the checksum itself into the new checksum
|
// Do not include the checksum itself into the new checksum
|
||||||
size_t size = offsetof(MIHP_HeapMemoryAreaHeader, Checksum);
|
size_t size = offsetof(MIHP_HeapMemoryAreaHeader, Checksum);
|
||||||
return MIHP_HashMemoryRegion(area, size);
|
return MIHP_HashMemoryRegion(area, size);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Invalid heap structure validation type"
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment)
|
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;
|
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);
|
MIHP_ASSERT(segment);
|
||||||
|
|
||||||
// Do not include the checksum itself into the new checksum
|
// Do not include the checksum itself into the new checksum
|
||||||
size_t size = offsetof(MIHP_HeapSegmentHeader, Checksum);
|
size_t size = offsetof(MIHP_HeapSegmentHeader, Checksum);
|
||||||
return MIHP_HashMemoryRegion(segment, size);
|
return MIHP_HashMemoryRegion(segment, size);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Invalid heap structure validation type"
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_HeapMemoryAreaHeader* area)
|
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_HeapMemoryAreaHeader* area)
|
||||||
{
|
{
|
||||||
#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION
|
uint32_t newChecksum;
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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)
|
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)
|
void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSegmentHeader* segment)
|
||||||
{
|
{
|
||||||
#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION
|
uint32_t newChecksum;
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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)
|
if (segment->Checksum != newChecksum)
|
||||||
{
|
{
|
||||||
@@ -529,4 +628,3 @@ void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSe
|
|||||||
MIHP_PlatformOnHeapCorruptionDetected(corruptionInfo);
|
MIHP_PlatformOnHeapCorruptionDetected(corruptionInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION 1
|
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE 0
|
||||||
#define MIHP_USE_CANARY_VALIDATION 1
|
#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_MEMORY_AREA_CHECKSUM_MISMATCH 0
|
||||||
#define MIHP_HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH 1
|
#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 */
|
/* 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_ASSERT(Condition) while(1) { if (Condition) break; *(volatile char*)(0x0) = 0; }
|
||||||
|
|
||||||
#define MIHP_HEAP_LOCK_TYPE uint8_t
|
#define MIHP_HEAP_LOCK_TYPE uint8_t // Does NOT have to be reentred safe
|
||||||
#define MIHP_LOCK_HEAP(LockVariablePtr) {}
|
#define MIHP_LOCK_HEAP(LockVarPtr) { while (*(LockVarPtr)) {}; *(LockVarPtr) = true; }
|
||||||
#define MIHP_UNLOCK_HEAP(LockVarialbePtr) {}
|
#define MIHP_UNLOCK_HEAP(LockVarPtr) { *(LockVarPtr) = false; }
|
||||||
/* === */
|
/* === */
|
||||||
|
|
||||||
typedef struct _MIHP_HeapInfo
|
typedef struct _MIHP_HeapInfo
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ void MIHP_PlatformOnHeapCorruptionDetected(MIHP_HeapCorruptionInfo info)
|
|||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NUM_ALLOCATIONS (4096 * 32)
|
#define NUM_ALLOCATIONS (4096 * 4)
|
||||||
|
|
||||||
void* myptrs[NUM_ALLOCATIONS] = { 0 };
|
void* myptrs[NUM_ALLOCATIONS] = { 0 };
|
||||||
|
|
||||||
@@ -67,15 +67,17 @@ int main()
|
|||||||
for (int i = 0; i < NUM_ALLOCATIONS; i++)
|
for (int i = 0; i < NUM_ALLOCATIONS; i++)
|
||||||
{
|
{
|
||||||
volatile int n = 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
|
#if USE_MALLOC
|
||||||
myptrs[i] = malloc(size);
|
myptrs[i] = realloc(myptrs[i], size);
|
||||||
#else
|
#else
|
||||||
myptrs[i] = MIHP_Allocate(myHeap, size);
|
myptrs[i] = MIHP_Realloc(myHeap, myptrs[i], size);
|
||||||
MIHP_ValidateHeap(myHeap);
|
MIHP_ValidateHeap(myHeap);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user