mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[RTL] Avoid some corner case ASSERT's in heap.c and fix heap allocations larger than MAXUSHORT. (#5750)
CORE-18196 With most code copied from Thomas Faber's PR #4915 as follows: [RTL] Correctly initialize segments larger than MAXUSHORT. GuardEntry->PreviousSize would overflow in this case. RtlpInsertFreeBlock already handles this correctly by creating multiple free entries. So we just let it return the last entry and use that for the PreviousSize. This does not include all of the ASSERT's in PR #4915.
This commit is contained in:
parent
f16e625c52
commit
7983297bd6
1 changed files with 28 additions and 9 deletions
|
@ -353,7 +353,8 @@ RtlpInsertFreeBlockHelper(PHEAP Heap,
|
|||
Heap->FreeHints[HintIndex] = &FreeEntry->FreeList;
|
||||
}
|
||||
|
||||
VOID NTAPI
|
||||
PHEAP_FREE_ENTRY
|
||||
NTAPI
|
||||
RtlpInsertFreeBlock(PHEAP Heap,
|
||||
PHEAP_FREE_ENTRY FreeEntry,
|
||||
SIZE_T BlockSize)
|
||||
|
@ -361,6 +362,7 @@ RtlpInsertFreeBlock(PHEAP Heap,
|
|||
USHORT Size, PreviousSize;
|
||||
UCHAR SegmentOffset, Flags;
|
||||
PHEAP_SEGMENT Segment;
|
||||
PHEAP_FREE_ENTRY LastEntry;
|
||||
|
||||
DPRINT("RtlpInsertFreeBlock(%p %p %x)\n", Heap, FreeEntry, BlockSize);
|
||||
|
||||
|
@ -368,6 +370,7 @@ RtlpInsertFreeBlock(PHEAP Heap,
|
|||
Heap->TotalFreeSize += BlockSize;
|
||||
|
||||
/* Remember certain values */
|
||||
LastEntry = FreeEntry;
|
||||
Flags = FreeEntry->Flags;
|
||||
PreviousSize = FreeEntry->PreviousSize;
|
||||
SegmentOffset = FreeEntry->SegmentOffset;
|
||||
|
@ -406,15 +409,21 @@ RtlpInsertFreeBlock(PHEAP Heap,
|
|||
BlockSize -= Size;
|
||||
|
||||
/* Go to the next entry */
|
||||
LastEntry = FreeEntry;
|
||||
FreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + Size);
|
||||
|
||||
/* Check if that's all */
|
||||
if ((PHEAP_ENTRY)FreeEntry >= Segment->LastValidEntry) return;
|
||||
if ((PHEAP_ENTRY)FreeEntry >= Segment->LastValidEntry)
|
||||
{
|
||||
return LastEntry;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update previous size if needed */
|
||||
if (!(Flags & HEAP_ENTRY_LAST_ENTRY))
|
||||
FreeEntry->PreviousSize = PreviousSize;
|
||||
|
||||
return LastEntry;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -426,6 +435,10 @@ RtlpRemoveFreeBlock(PHEAP Heap,
|
|||
SIZE_T Result, RealSize;
|
||||
ULONG HintIndex;
|
||||
|
||||
/* This was a problem before we handled segments > MAXUSHORT.
|
||||
* It may not be needed now, but is left just for safety. */
|
||||
ASSERT(FreeEntry->Size != 0);
|
||||
|
||||
/* Remove the free block */
|
||||
if (FreeEntry->Size > Heap->DeCommitFreeBlockThreshold)
|
||||
HintIndex = 0;
|
||||
|
@ -1060,17 +1073,20 @@ RtlpInitializeHeapSegment(IN OUT PHEAP Heap,
|
|||
{
|
||||
/* Ensure we put our guard entry at the end of the last committed page */
|
||||
PHEAP_ENTRY GuardEntry = &Segment->Entry + (SegmentCommit >> HEAP_ENTRY_SHIFT) - 1;
|
||||
SIZE_T PreviousSize;
|
||||
|
||||
ASSERT(GuardEntry > &Segment->Entry);
|
||||
GuardEntry->Size = 1;
|
||||
GuardEntry->Flags = HEAP_ENTRY_BUSY | HEAP_ENTRY_LAST_ENTRY;
|
||||
GuardEntry->SegmentOffset = SegmentIndex;
|
||||
GuardEntry->PreviousSize = GuardEntry - Segment->FirstEntry;
|
||||
PreviousSize = GuardEntry - Segment->FirstEntry;
|
||||
|
||||
/* Chack what is left behind us */
|
||||
switch (GuardEntry->PreviousSize)
|
||||
/* Check what is left behind us */
|
||||
switch (PreviousSize)
|
||||
{
|
||||
case 1:
|
||||
GuardEntry->PreviousSize = PreviousSize;
|
||||
|
||||
/* There is not enough space for a free entry. Double the guard entry */
|
||||
GuardEntry--;
|
||||
GuardEntry->Size = 1;
|
||||
|
@ -1087,8 +1103,12 @@ RtlpInitializeHeapSegment(IN OUT PHEAP Heap,
|
|||
FreeEntry = Segment->FirstEntry;
|
||||
FreeEntry->PreviousSize = Segment->Entry.Size;
|
||||
FreeEntry->SegmentOffset = SegmentIndex;
|
||||
FreeEntry->Size = GuardEntry->PreviousSize;
|
||||
FreeEntry->Size = PreviousSize;
|
||||
FreeEntry->Flags = 0;
|
||||
|
||||
/* Register the Free Heap Entry */
|
||||
FreeEntry = (PHEAP_ENTRY)RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)FreeEntry, PreviousSize);
|
||||
GuardEntry->PreviousSize = FreeEntry->Size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1100,11 +1120,10 @@ RtlpInitializeHeapSegment(IN OUT PHEAP Heap,
|
|||
FreeEntry->SegmentOffset = SegmentIndex;
|
||||
FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
|
||||
FreeEntry->Size = (SegmentCommit >> HEAP_ENTRY_SHIFT) - Segment->Entry.Size;
|
||||
}
|
||||
|
||||
/* Register the Free Heap Entry */
|
||||
if (FreeEntry)
|
||||
/* Register the Free Heap Entry */
|
||||
RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)FreeEntry, FreeEntry->Size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register the UnCommitted Range of the Heap Segment */
|
||||
|
|
Loading…
Reference in a new issue