aboutsummaryrefslogtreecommitdiff
path: root/src/SFileListFile.cpp
diff options
context:
space:
mode:
authorLadislav Zezula <ladislav.zezula@avast.com>2022-02-13 07:40:22 +0100
committerLadislav Zezula <ladislav.zezula@avast.com>2022-02-13 07:40:22 +0100
commit503ab19d3d4253fb013752572c19c314d19de792 (patch)
treeb1f026437af9411ffd216e5406bfec4cd899e75a /src/SFileListFile.cpp
parent6a107601c628ec15b5d7947d6f51d00d709b0e7a (diff)
SFileAddListFile optimized for protectors that set too large hash table
Diffstat (limited to 'src/SFileListFile.cpp')
-rw-r--r--src/SFileListFile.cpp42
1 files changed, 33 insertions, 9 deletions
diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp
index a1e16b0..8ce9ae4 100644
--- a/src/SFileListFile.cpp
+++ b/src/SFileListFile.cpp
@@ -409,8 +409,10 @@ static LPBYTE CreateListFile(TMPQArchive * ha, DWORD * pcbListFile)
static DWORD SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szFileName)
{
TFileEntry * pFileEntry;
- TMPQHash * pFirstHash;
+ TMPQHash * pHashEnd;
TMPQHash * pHash;
+ DWORD dwName1;
+ DWORD dwName2;
// If we have HET table, use that one
if(ha->pHetTable != NULL)
@@ -428,17 +430,39 @@ static DWORD SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szF
// If we have hash table, we use it
if(ha->pHashTable != NULL)
{
- // Go while we found something
- pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
- while(pHash != NULL)
+ // Get the end of the hash table and both names
+ pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
+ dwName1 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_A);
+ dwName2 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_B);
+
+ // Some protectors set very high hash table size (0x00400000 items or more)
+ // in order to make this process very slow. We will ignore items
+ // in the hash table that would be beyond the end of the file.
+ // Example MPQ: MPQ_2022_v1_Sniper.scx
+ if(ha->dwFlags & MPQ_FLAG_HASH_TABLE_CUT)
+ pHashEnd = ha->pHashTable + (ha->dwRealHashTableSize / sizeof(TMPQHash));
+
+ // Go through the hash table and put the name in each item that has the same name pair
+ for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
{
- // Allocate file name for the file entry
- AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
-
- // Now find the next language version of the file
- pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
+ {
+ // Allocate file name for the file entry
+ AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
+ }
}
+ // Go while we found something
+ //pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
+ //while(pHash != NULL)
+ //{
+ // // Allocate file name for the file entry
+ // AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
+
+ // // Now find the next language version of the file
+ // pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ //}
+
return ERROR_SUCCESS;
}