aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLadislav Zezula <zezula@volny.cz>2023-06-06 09:50:16 +0200
committerLadislav Zezula <zezula@volny.cz>2023-06-06 09:50:16 +0200
commitafd304b180607a68edc1613074eeaca5e8805153 (patch)
tree161b1c1622d5d43e333bd73272173f83cc6e910e
parent1e436d61fe963d58235af5b898f0e70a18bbb550 (diff)
Fixed loading of corrupt MPQ version 2
-rw-r--r--StormLib.sln (renamed from StormLib_vs22.sln)6
-rw-r--r--StormLib.vcxproj (renamed from StormLib_vs22.vcxproj)0
-rw-r--r--StormLib.vcxproj.filters (renamed from StormLib_vs22.vcxproj.filters)0
-rw-r--r--StormLib_dll.vcxproj (renamed from StormLib_vs22_dll.vcxproj)0
-rw-r--r--StormLib_dll.vcxproj.filters (renamed from StormLib_vs22_dll.vcxproj.filters)0
-rw-r--r--StormLib_test.vcxproj (renamed from StormLib_vs22_test.vcxproj)0
-rw-r--r--StormLib_test.vcxproj.filters (renamed from StormLib_vs22_test.vcxproj.filters)0
-rw-r--r--make-msvc.bat4
-rw-r--r--src/SBaseFileTable.cpp58
-rw-r--r--test/StormTest.cpp27
10 files changed, 57 insertions, 38 deletions
diff --git a/StormLib_vs22.sln b/StormLib.sln
index 1d6f972..0ce51bc 100644
--- a/StormLib_vs22.sln
+++ b/StormLib.sln
@@ -2,11 +2,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2050
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib", "StormLib_vs22.vcxproj", "{78424708-1F6E-4D4B-920C-FB6D26847055}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib", "StormLib.vcxproj", "{78424708-1F6E-4D4B-920C-FB6D26847055}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib_dll", "StormLib_vs22_dll.vcxproj", "{CB385198-50B1-4CF4-883B-11F042DED6AA}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib_dll", "StormLib_dll.vcxproj", "{CB385198-50B1-4CF4-883B-11F042DED6AA}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib_test", "StormLib_vs22_test.vcxproj", "{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib_test", "StormLib_test.vcxproj", "{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/StormLib_vs22.vcxproj b/StormLib.vcxproj
index 26d8f70..26d8f70 100644
--- a/StormLib_vs22.vcxproj
+++ b/StormLib.vcxproj
diff --git a/StormLib_vs22.vcxproj.filters b/StormLib.vcxproj.filters
index 22c9793..22c9793 100644
--- a/StormLib_vs22.vcxproj.filters
+++ b/StormLib.vcxproj.filters
diff --git a/StormLib_vs22_dll.vcxproj b/StormLib_dll.vcxproj
index bda8dd9..bda8dd9 100644
--- a/StormLib_vs22_dll.vcxproj
+++ b/StormLib_dll.vcxproj
diff --git a/StormLib_vs22_dll.vcxproj.filters b/StormLib_dll.vcxproj.filters
index 2eaf026..2eaf026 100644
--- a/StormLib_vs22_dll.vcxproj.filters
+++ b/StormLib_dll.vcxproj.filters
diff --git a/StormLib_vs22_test.vcxproj b/StormLib_test.vcxproj
index 18cee5b..18cee5b 100644
--- a/StormLib_vs22_test.vcxproj
+++ b/StormLib_test.vcxproj
diff --git a/StormLib_vs22_test.vcxproj.filters b/StormLib_test.vcxproj.filters
index d341b12..d341b12 100644
--- a/StormLib_vs22_test.vcxproj.filters
+++ b/StormLib_test.vcxproj.filters
diff --git a/make-msvc.bat b/make-msvc.bat
index d2d06d3..3dbc675 100644
--- a/make-msvc.bat
+++ b/make-msvc.bat
@@ -27,8 +27,8 @@ if exist "%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Enterprise\VC\Auxilia
:: Build all libraries using Visual Studio 2008 and 2019
if not "x%VCVARS_2008%" == "x" call :BuildLibs "%VCVARS_2008%" x86 %LIB_NAME%_vs08.sln \vs2008
if not "x%VCVARS_2008%" == "x" call :BuildLibs "%VCVARS_2008%" x64 %LIB_NAME%_vs08.sln \vs2008
-if not "x%VCVARS_20xx%" == "x" call :BuildLibs "%VCVARS_20xx%" x86 %LIB_NAME%_vs22.sln
-if not "x%VCVARS_20xx%" == "x" call :BuildLibs "%VCVARS_20xx%" x64 %LIB_NAME%_vs22.sln
+if not "x%VCVARS_20xx%" == "x" call :BuildLibs "%VCVARS_20xx%" x86 %LIB_NAME%.sln
+if not "x%VCVARS_20xx%" == "x" call :BuildLibs "%VCVARS_20xx%" x64 %LIB_NAME%.sln
goto:eof
::-----------------------------------------------------------------------------
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp
index 43202d0..20d7cc4 100644
--- a/src/SBaseFileTable.cpp
+++ b/src/SBaseFileTable.cpp
@@ -317,29 +317,54 @@ static ULONGLONG DetermineArchiveSize_V2(
ULONGLONG MpqOffset,
ULONGLONG FileSize)
{
- ULONGLONG EndOfMpq = FileSize;
- DWORD dwArchiveSize32;
+ ULONGLONG TableOffset;
+ ULONGLONG TableSize;
+ ULONGLONG MaxOffset = 0;
// This could only be called for MPQs version 2.0
assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_2);
- // Check if we can rely on the archive size in the header
- if((FileSize >> 0x20) == 0)
+ // Is the hash table end greater than max offset?
+ TableOffset = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
+ TableSize = (ULONGLONG)pHeader->dwHashTableSize * sizeof(TMPQHash);
+ if((TableOffset + TableSize) > MaxOffset)
+ MaxOffset = TableOffset + TableSize;
+
+ // Is the block table end greater than max offset?
+ TableOffset = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ TableSize = (ULONGLONG)pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ if((TableOffset + TableSize) > MaxOffset)
+ MaxOffset = TableOffset + TableSize;
+
+ // Is the hi-block table end greater than max offset?
+ if((TableOffset = pHeader->HiBlockTablePos64) != 0)
{
- if(pHeader->dwBlockTablePos < pHeader->dwArchiveSize)
- {
- if((pHeader->dwArchiveSize - pHeader->dwBlockTablePos) <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock)))
- return pHeader->dwArchiveSize;
+ TableSize = (ULONGLONG)pHeader->dwBlockTableSize * sizeof(USHORT);
+ if((TableOffset + TableSize) > MaxOffset)
+ MaxOffset = TableOffset + TableSize;
+ }
+
+ // Cut to the file size
+ if(MaxOffset > (FileSize - MpqOffset))
+ MaxOffset = FileSize - MpqOffset;
+ return MaxOffset;
+}
+
+static ULONGLONG DetermineBlockTableSize_V2(TMPQHeader * pHeader)
+{
+ ULONGLONG BlockTableOffset = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ ULONGLONG TableOffset;
+ ULONGLONG TableSize = (pHeader->ArchiveSize64 - BlockTableOffset);
- // If the archive size in the header is less than real file size
- dwArchiveSize32 = (DWORD)(FileSize - MpqOffset);
- if(pHeader->dwArchiveSize <= dwArchiveSize32)
- return pHeader->dwArchiveSize;
+ // Subtract the offset of the hi-block table
+ if((TableOffset = pHeader->HiBlockTablePos64) != 0)
+ {
+ if(TableOffset > BlockTableOffset)
+ {
+ TableSize = TableOffset - BlockTableOffset;
}
}
-
- // Return the calculated archive size
- return (EndOfMpq - MpqOffset);
+ return TableSize;
}
static ULONGLONG DetermineArchiveSize_V4(
@@ -564,9 +589,10 @@ DWORD ConvertMpqHeaderToFormat4(
{
// Determine real archive size
pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, ByteOffset, FileSize);
+ pHeader->dwArchiveSize = (DWORD)(pHeader->ArchiveSize64);
// Calculate size of the block table
- pHeader->BlockTableSize64 = pHeader->ArchiveSize64 - BlockTablePos64;
+ pHeader->BlockTableSize64 = DetermineBlockTableSize_V2(pHeader);
assert(pHeader->BlockTableSize64 <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock)));
}
}
diff --git a/test/StormTest.cpp b/test/StormTest.cpp
index 2f45e96..82668cf 100644
--- a/test/StormTest.cpp
+++ b/test/StormTest.cpp
@@ -4183,30 +4183,23 @@ int _tmain(int argc, TCHAR * argv[])
// Initialize storage and mix the random number generator
printf("==== Test Suite for StormLib version %s ====\n", STORMLIB_VERSION_STRING);
dwErrCode = InitializeMpqDirectory(argv, argc);
-/*
+
// Check creation of the MPQ with LZMA compression
- LPCTSTR szArchiveName = _T("E:\\new-mpq.mpq");
+ LPCTSTR szArchiveName = _T("e:\\MemoryCorruption.SC2Replay");
HANDLE hFile = NULL;
HANDLE hMpq = NULL;
-
- DeleteFile(szArchiveName);
- if(SFileCreateArchive(szArchiveName, MPQ_CREATE_ARCHIVE_V2 | MPQ_CREATE_LISTFILE | MPQ_CREATE_ATTRIBUTES, 0x1000, &hMpq))
+/*
+ if(SFileOpenArchive(szArchiveName, 0, 0, &hMpq))
{
- SFileAddFileEx(hMpq, _T("e:\\DlgSearchFile.cpp"), "DlgSearchFile.cpp", MPQ_FILE_SINGLE_UNIT | MPQ_FILE_COMPRESS, MPQ_COMPRESSION_LZMA, MPQ_COMPRESSION_NEXT_SAME);
- SFileCloseArchive(hMpq);
-
- if(SFileOpenArchive(szArchiveName, 0, 0, &hMpq))
+ if(SFileOpenFileEx(hMpq, "DlgSearchFile.cpp", 0, &hFile))
{
- if(SFileOpenFileEx(hMpq, "DlgSearchFile.cpp", 0, &hFile))
- {
- DWORD dwBytesRead = 0;
- BYTE Buffer[0x100];
+ DWORD dwBytesRead = 0;
+ BYTE Buffer[0x100];
- SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
- SFileCloseFile(hFile);
- }
- SFileCloseArchive(hMpq);
+ SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
+ SFileCloseFile(hFile);
}
+ SFileCloseArchive(hMpq);
}
*/
#ifdef TEST_COMMAND_LINE