RtlpCoalesceFreeBlocks
_HEAP_FREE_ENTRY *__stdcall RtlpCoalesceFreeBlocks(
_HEAP *Heap,
_HEAP_FREE_ENTRY *FreeBlock,
UINT64 *FreeSize,
UINT64 *RemoveFromFreeList,
UINT64 *a5,
VOID *a6){
_HEAP_FREE_ENTRY *v7;
unsigned __int64 v8;
_HEAP_FREE_ENTRY *v10;
unsigned int EncodeFlagMask;
VOID **p_Flink;
_LIST_ENTRY *p_FreeList;
_LIST_ENTRY *Flink;
_LIST_ENTRY *v15;
_LIST_ENTRY *Blink;
_HEAP_LIST_LOOKUP *BlocksIndex;
unsigned __int64 i;
_HEAP_LIST_LOOKUP *ExtendedLookup;
int Size;
char Flags;
unsigned __int64 v22;
__int64 v23;
__int64 v24;
UINT64 v25;
unsigned int v26;
VOID **v27;
_QWORD *v28;
VOID *v29;
VOID *v30;
_HEAP_LIST_LOOKUP *v31;
unsigned __int64 j;
_HEAP_LIST_LOOKUP *v33;
_LIST_ENTRY *v34;
char v35;
unsigned __int64 v36;
__int64 v37;
UINT64 Context;
v7 = FreeBlock;
v8 = 16
* (Heap->Encoding.UnpackedEntry.PreviousSize ^ (unsigned __int64)FreeBlock->HeapEntry.UnpackedEntry.PreviousSize);
v10 = (_HEAP_FREE_ENTRY *)((char *)FreeBlock - v8);
if( (_HEAP_FREE_ENTRY *)((char *)FreeBlock - v8) != FreeBlock )
{
EncodeFlagMask = Heap->EncodeFlagMask;
if( ((v10->HeapEntry.UnpackedEntry.Flags ^ Heap->Encoding.UnpackedEntry.Flags & (EncodeFlagMask >> 20)) & 1) == 0 )
{
if( EncodeFlagMask )
{
v10->HeapEntry.UnpackedEntry.SubSegmentCode ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
if( v10->HeapEntry.UnpackedEntry.SmallTagIndex != (LOBYTE(v10->InterceptorValue) ^ (unsigned __int8)(BYTE1(v10->Code1) ^ v10->HeapEntry.UnpackedEntry.Flags)) )
RtlpAnalyzeHeapFailure(Heap, (_HEAP_ENTRY *)((char *)&FreeBlock->HeapEntry - v8));
}
p_Flink = (VOID **)&v10->FreeList.Blink->Flink;
p_FreeList = &v10->FreeList;
Flink = v10->FreeList.Flink;
v15 = (_LIST_ENTRY *)*p_Flink;
Blink = Flink->Blink;
if( *p_Flink == Blink && v15 == p_FreeList )
{
Heap->TotalFreeSize -= v10->HeapEntry.UnpackedEntry.Size;
BlocksIndex = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
if( BlocksIndex )
{
for( i = BlocksIndex->ArraySize; ; i = ExtendedLookup->ArraySize )
{
if( v10->HeapEntry.UnpackedEntry.Size < i )
{
Size = v10->HeapEntry.UnpackedEntry.Size;
goto LABEL_14;
}
ExtendedLookup = BlocksIndex->ExtendedLookup;
if( !BlocksIndex->ExtendedLookup )
break;
BlocksIndex = BlocksIndex->ExtendedLookup;
}
Size = BlocksIndex->ArraySize - 1;
LABEL_14:
LODWORD(Context) = Size;
LOBYTE(p_FreeList) = 1;
RtlpHeapRemoveListEntry(Heap, BlocksIndex, p_FreeList, (UINT64)&v10->FreeList, Context);
}
*p_Flink = Flink;
Flink->Blink = (_LIST_ENTRY *)p_Flink;
Flags = v10->HeapEntry.UnpackedEntry.Flags;
if( (Flags & 4) != 0 )
{
v22 = 16i64 * v10->HeapEntry.UnpackedEntry.Size - 32;
if( (Flags & 2) != 0 && v22 > 4 )
v22 = 16i64 * v10->HeapEntry.UnpackedEntry.Size - 36;
LODWORD(v23) = RtlCompareMemoryUlong(&v10[1], v22, 0xFEEEFEEEui64);
if( v23 != v22 )
{
DbgPrint("HEAP: Free Heap block %p modified at %p after it was freed\n", v10, (char *)&v10[1] + v23);
if( (_BYTE)KdDebuggerEnabled )
__debugbreak();
}
}
v24 = v10->HeapEntry.UnpackedEntry.Size;
v7 = v10;
v10->HeapEntry.UnpackedEntry.Flags = 0;
v10->HeapEntry.UnpackedEntry.UnusedBytes = 0;
*FreeSize += v24;
v10->HeapEntry.UnpackedEntry.Size = *(_WORD *)FreeSize;
*(&v10->HeapEntry.UnpackedEntry.PreviousSize + 8 * *FreeSize) = Heap->Encoding.UnpackedEntry.PreviousSize ^ *(_WORD *)FreeSize;
}
else
{
RtlpLogHeapFailure(heap_failure_freelists_corruption, Heap, p_FreeList, Blink, v15);
}
}
}
v25 = (UINT64)v7 + 16 * *FreeSize;
if( Heap->EncodeFlagMask )
{
v26 = *(_DWORD *)(v25 + 8) ^ Heap->Encoding.UnpackedEntry.SubSegmentCode;
if( HIBYTE(v26) != ((unsigned __int8)v26 ^ (unsigned __int8)(BYTE1(v26) ^ BYTE2(v26))) )
RtlpLogHeapFailure(heap_failure_entry_corruption, Heap, (VOID *)v25, 0i64, 0i64);
}
while( ((*(_BYTE *)(v25 + 10) ^ Heap->Encoding.UnpackedEntry.Flags & (Heap->EncodeFlagMask >> 20)) & 1) == 0 )
{
if( Heap->EncodeFlagMask )
{
*(_DWORD *)(v25 + 8) ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
if( *(_BYTE *)(v25 + 11) != (*(_BYTE *)(v25 + 8) ^ (unsigned __int8)(*(_BYTE *)(v25 + 9) ^ *(_BYTE *)(v25 + 10))) )
RtlpAnalyzeHeapFailure(Heap, (_HEAP_ENTRY *)v25);
}
v27 = *(VOID ***)(v25 + 24);
v28 = *(_QWORD **)(v25 + 16);
v29 = *v27;
v30 = (VOID *)v28[1];
if( *v27 == v30 && v29 == (VOID *)(v25 + 16) )
{
Heap->TotalFreeSize -= *(unsigned __int16 *)(v25 + 8);
v31 = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
if( v31 )
{
for( j = v31->ArraySize; ; j = v33->ArraySize )
{
if( *(unsigned __int16 *)(v25 + 8) < j )
{
v34 = (_LIST_ENTRY *)*(unsigned __int16 *)(v25 + 8);
goto LABEL_41;
}
v33 = v31->ExtendedLookup;
if( !v31->ExtendedLookup )
break;
v31 = v31->ExtendedLookup;
}
v34 = (_LIST_ENTRY *)(v31->ArraySize - 1);
LABEL_41:
LODWORD(Context) = (_DWORD)v34;
LOBYTE(v34) = 1;
RtlpHeapRemoveListEntry(Heap, v31, v34, v25 + 16, Context);
}
*v27 = v28;
v28[1] = v27;
v35 = *(_BYTE *)(v25 + 10);
if( (v35 & 4) != 0 )
{
v36 = 16i64 * *(unsigned __int16 *)(v25 + 8) - 32;
if( (v35 & 2) != 0 && v36 > 4 )
v36 = 16i64 * *(unsigned __int16 *)(v25 + 8) - 36;
LODWORD(v37) = RtlCompareMemoryUlong((VOID *)(v25 + 32), v36, 0xFEEEFEEEui64);
if( v37 != v36 )
{
DbgPrint(
"HEAP: Free Heap block %p modified at %p after it was freed\n",
(const void *)v25,
(const void *)(v37 + v25 + 32));
if( (_BYTE)KdDebuggerEnabled )
__debugbreak();
}
}
v7->HeapEntry.UnpackedEntry.Flags = 0;
v7->HeapEntry.UnpackedEntry.UnusedBytes = 0;
*FreeSize += *(unsigned __int16 *)(v25 + 8);
v7->HeapEntry.UnpackedEntry.Size = *(_WORD *)FreeSize;
*(&v7->HeapEntry.UnpackedEntry.PreviousSize + 8 * *FreeSize) = Heap->Encoding.UnpackedEntry.PreviousSize ^ *(_WORD *)FreeSize;
return v7;
}
RtlpLogHeapFailure(heap_failure_freelists_corruption, Heap, (VOID *)(v25 + 16), v30, v29);
}
return v7;
}Referenced by:
RtlpDeCommitFreeBlock
RtlpExtendHeap
RtlpFreeHeap