mirror of
https://github.com/ladislav-zezula/StormLib.git
synced 2026-01-20 14:47:22 +01:00
+ Updated for protectors fiddling with too big block table index
This commit is contained in:
@@ -581,11 +581,9 @@ int ConvertMpqHeaderToFormat4(
|
||||
// Hash entry verification when the file table does not exist yet
|
||||
bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash)
|
||||
{
|
||||
TFileEntry * pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
|
||||
DWORD dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
|
||||
TFileEntry * pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
|
||||
|
||||
pFileEntry = ha->pFileTable + dwBlockIndex;
|
||||
return ((dwBlockIndex < ha->dwFileTableSize) && (pFileEntry->dwFlags & MPQ_FILE_EXISTS)) ? true : false;
|
||||
return ((MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) && (pFileEntry->dwFlags & MPQ_FILE_EXISTS)) ? true : false;
|
||||
}
|
||||
|
||||
// Hash entry verification when the file table does not exist yet
|
||||
@@ -593,20 +591,12 @@ static bool IsValidHashEntry1(TMPQArchive * ha, TMPQHash * pHash, TMPQBlock * pB
|
||||
{
|
||||
ULONGLONG ByteOffset;
|
||||
TMPQBlock * pBlock;
|
||||
DWORD dwBlockIndex;
|
||||
|
||||
// We need to mask out the upper 4 bits of the block table index.
|
||||
// This is because it gets shifted out when calculating block table offset
|
||||
// BlockTableOffset = pHash->dwBlockIndex * 0x10
|
||||
// Malformed MPQ maps may contain invalid entries
|
||||
// Note that Storm.dll does not perfom this check
|
||||
dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
|
||||
|
||||
// The block index is considered valid if it's less than block table size
|
||||
if(dwBlockIndex < ha->pHeader->dwBlockTableSize)
|
||||
if(MPQ_BLOCK_INDEX(pHash) < ha->pHeader->dwBlockTableSize)
|
||||
{
|
||||
// Calculate the block table position
|
||||
pBlock = pBlockTable + dwBlockIndex;
|
||||
pBlock = pBlockTable + MPQ_BLOCK_INDEX(pHash);
|
||||
|
||||
// Check whether this is an existing file
|
||||
// Also we do not allow to be file size greater than 2GB
|
||||
@@ -787,28 +777,28 @@ static int BuildFileTableFromBlockTable(
|
||||
// - Multiple hash entries (different file name) point to the same block entry
|
||||
//
|
||||
// Ignore all hash table entries where:
|
||||
// - dwBlockIndex >= BlockTableSize
|
||||
// - Block Index >= BlockTableSize
|
||||
// - Flags of the appropriate block table entry
|
||||
//
|
||||
|
||||
if(IsValidHashEntry1(ha, pHash, pBlockTable))
|
||||
{
|
||||
DWORD dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
|
||||
DWORD dwNewIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
|
||||
DWORD dwOldIndex = MPQ_BLOCK_INDEX(pHash);
|
||||
DWORD dwNewIndex = MPQ_BLOCK_INDEX(pHash);
|
||||
|
||||
// Determine the new block index
|
||||
if(DefragmentTable != NULL)
|
||||
{
|
||||
// Need to handle case when multiple hash
|
||||
// entries point to the same block entry
|
||||
if(DefragmentTable[dwBlockIndex] == HASH_ENTRY_FREE)
|
||||
if(DefragmentTable[dwOldIndex] == HASH_ENTRY_FREE)
|
||||
{
|
||||
DefragmentTable[dwBlockIndex] = dwItemCount;
|
||||
DefragmentTable[dwOldIndex] = dwItemCount;
|
||||
dwNewIndex = dwItemCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwNewIndex = DefragmentTable[dwBlockIndex];
|
||||
dwNewIndex = DefragmentTable[dwOldIndex];
|
||||
}
|
||||
|
||||
// Fix the pointer in the hash entry
|
||||
@@ -820,7 +810,7 @@ static int BuildFileTableFromBlockTable(
|
||||
|
||||
// Get the pointer to the file entry and the block entry
|
||||
pFileEntry = ha->pFileTable + dwNewIndex;
|
||||
pBlock = pBlockTable + dwBlockIndex;
|
||||
pBlock = pBlockTable + dwOldIndex;
|
||||
|
||||
// ByteOffset is only valid if file size is not zero
|
||||
pFileEntry->ByteOffset = pBlock->dwFilePos;
|
||||
@@ -1814,11 +1804,11 @@ TFileEntry * GetFileEntryLocale2(TMPQArchive * ha, const char * szFileName, LCID
|
||||
if(ha->pHashTable != NULL)
|
||||
{
|
||||
pHash = GetHashEntryLocale(ha, szFileName, lcLocale);
|
||||
if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize)
|
||||
if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
|
||||
{
|
||||
if(PtrHashIndex != NULL)
|
||||
PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
|
||||
return ha->pFileTable + pHash->dwBlockIndex;
|
||||
return ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1848,11 +1838,11 @@ TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID l
|
||||
if(ha->pHashTable != NULL)
|
||||
{
|
||||
pHash = GetHashEntryExact(ha, szFileName, lcLocale);
|
||||
if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize)
|
||||
if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
|
||||
{
|
||||
if(PtrHashIndex != NULL)
|
||||
PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
|
||||
return ha->pFileTable + pHash->dwBlockIndex;
|
||||
return ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2640,11 +2630,11 @@ int DefragmentFileTable(TMPQArchive * ha)
|
||||
|
||||
for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++)
|
||||
{
|
||||
if(pHash->dwBlockIndex < ha->dwFileTableSize)
|
||||
if(MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
|
||||
{
|
||||
// If that block entry is there, set it to the hash entry
|
||||
// If not, set it as DELETED
|
||||
dwNewBlockIndex = DefragmentTable[pHash->dwBlockIndex];
|
||||
dwNewBlockIndex = DefragmentTable[MPQ_BLOCK_INDEX(pHash)];
|
||||
pHash->dwBlockIndex = (dwNewBlockIndex != HASH_ENTRY_FREE) ? dwNewBlockIndex : HASH_ENTRY_DELETED;
|
||||
}
|
||||
}
|
||||
@@ -2753,7 +2743,7 @@ int RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize)
|
||||
{
|
||||
if(IsValidHashEntry(ha, pHash))
|
||||
{
|
||||
pFileEntry = ha->pFileTable + pHash->dwBlockIndex;
|
||||
pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
|
||||
AllocateHashEntry(ha, pFileEntry, pHash->lcLocale);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user