From e9842c38cf9c55f682b2a411cea84ee59d69ec92 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Tue, 23 Dec 2014 15:04:35 +0100 Subject: + Adding files into MPQs that have BlockTableSize > HashTableSize is not allowed + Compacting MPQs that have BlockTableSize > HashTableSize is allowed --- src/SBaseFileTable.cpp | 7 +++++-- src/SFileAddFile.cpp | 8 ++++++++ test/StormTest.cpp | 32 +++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 2d6249f..68ad0d7 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -2629,7 +2629,6 @@ int RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize, DWORD dwNewMaxF // The new hash table size must be greater or equal to the current hash table size assert(dwNewHashTableSize >= ha->pHeader->dwHashTableSize); - assert(dwNewMaxFileCount >= ha->dwFileTableSize); // The new hash table size must be a power of two assert((dwNewHashTableSize & (dwNewHashTableSize - 1)) == 0); @@ -2676,7 +2675,11 @@ int RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize, DWORD dwNewMaxF if(ha->pHashTable != NULL) { pHash = AllocateHashEntry(ha, pFileEntry); - assert(pHash != NULL); + if(pHash == NULL) + { + nError = ERROR_DISK_FULL; + break; + } } // Move the file entry by one diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index 5997c1b..524fb50 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -725,6 +725,14 @@ bool WINAPI SFileCreateFile( nError = ERROR_INVALID_PARAMETER; } + // Check for MPQs that have invalid block table size + // Example: size of block table: 0x41, size of hash table: 0x40 + if(nError == ERROR_SUCCESS) + { + if(ha->dwFileTableSize > ha->dwMaxFileCount) + nError = ERROR_DISK_FULL; + } + // Initiate the add file operation if(nError == ERROR_SUCCESS) nError = SFileAddFile_Init(ha, szArchivedName, FileTime, dwFileSize, lcLocale, dwFlags, (TMPQFile **)phFile); diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 30a377b..70d6db0 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -2968,6 +2968,32 @@ static int ForEachFile_OpenArchive(const char * szFullPath) return nError; } +// Adding a file to MPQ that had no (listfile) and no (attributes). +// We expect that neither of these will be present after the archive is closed +static int TestAddFile_FullArchive(const char * szSourceMpq) +{ + TLogHelper Logger("FullMpqTest", szSourceMpq); + const char * szFileName = "AddedFile001.txt"; + const char * szFileData = "0123456789ABCDEF"; + HANDLE hMpq = NULL; + int nError = ERROR_SUCCESS; + + // Copy the archive so we won't fuck up the original one + nError = OpenExistingArchiveWithCopy(&Logger, szSourceMpq, szSourceMpq, &hMpq); + + // Add a file + if(nError == ERROR_SUCCESS) + { + // Now add a file + nError = AddFileToMpq(&Logger, hMpq, szFileName, szFileData, MPQ_FILE_IMPLODE, MPQ_COMPRESSION_PKWARE); + nError = (nError == ERROR_DISK_FULL) ? ERROR_SUCCESS : ERROR_FILE_CORRUPT; + + SFileCloseArchive(hMpq); + } + + return nError; +} + // Adding a file to MPQ that had no (listfile) and no (attributes). // We expect that neither of these will be present after the archive is closed static int TestAddFile_ListFileTest(const char * szSourceMpq, bool bShouldHaveListFile, bool bShouldHaveAttributes) @@ -4101,7 +4127,7 @@ int main(int argc, char * argv[]) // Open a patched archive if(nError == ERROR_SUCCESS) nError = TestOpenArchive_Patched(PatchList_SC2_32283_enGB, "LocalizedData\\GameHotkeys.txt", 6); -*/ + // Open a patched archive if(nError == ERROR_SUCCESS) nError = TestOpenArchive_Patched(PatchList_HS_6898_enGB, "Hearthstone_Data\\Managed\\Assembly-Csharp.dll", 10); @@ -4148,6 +4174,10 @@ int main(int argc, char * argv[]) // if(nError == ERROR_SUCCESS) // nError = TestOpenArchive_CompactingTest("MPQ_2014_v1_CompactTest.w3x", "ListFile_Blizzard.txt"); +*/ + // Test adding a file to MPQ that is already full + if(nError == ERROR_SUCCESS) + nError = TestAddFile_FullArchive("MPQ_2014_v1_out.w3x"); // Test modifying file with no (listfile) and no (attributes) if(nError == ERROR_SUCCESS) -- cgit v1.2.3