aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SBaseCommon.cpp16
-rw-r--r--src/SBaseFileTable.cpp13
-rw-r--r--src/SFileAddFile.cpp2
-rw-r--r--src/SFileReadFile.cpp6
4 files changed, 22 insertions, 15 deletions
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp
index ecbfc05..0d9598a 100644
--- a/src/SBaseCommon.cpp
+++ b/src/SBaseCommon.cpp
@@ -1026,12 +1026,19 @@ void * LoadMpqTable(
// and the table is loaded from the current file offset
if(ByteOffset == SFILE_INVALID_POS)
FileStream_GetPos(ha->pStream, &ByteOffset);
+ FileStream_GetSize(ha->pStream, &FileSize);
+
+ // Is the sector table within the file?
+ if(ByteOffset >= FileSize)
+ {
+ STORM_FREE(pbMpqTable);
+ return NULL;
+ }
// The hash table and block table can go beyond EOF.
// Storm.dll reads as much as possible, then fills the missing part with zeros.
// Abused by Spazzler map protector which sets hash table size to 0x00100000
// Abused by NP_Protect in MPQs v4 as well
- FileStream_GetSize(ha->pStream, &FileSize);
if((ByteOffset + dwBytesToRead) > FileSize)
{
// Fill the extra data with zeros
@@ -1358,14 +1365,17 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile)
if((hf->SectorOffsets[0] & 0xFFFFFFFC) > dwSectorOffsLen)
{
// MPQ protectors put some ridiculous values there. We must limit the extra bytes
- if(hf->SectorOffsets[0] > (dwSectorOffsLen + 0x400)) {
+ if(hf->SectorOffsets[0] > (dwSectorOffsLen + 0x400))
+ {
STORM_FREE(hf->SectorOffsets);
hf->SectorOffsets = NULL;
return ERROR_FILE_CORRUPT;
}
+ // The new length of the sector offset must be aligned to DWORD
+ dwSectorOffsLen = (hf->SectorOffsets[0] & 0xFFFFFFFC);
+
// Free the old sector offset table
- dwSectorOffsLen = hf->SectorOffsets[0];
STORM_FREE(hf->SectorOffsets);
goto __LoadSectorOffsets;
}
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp
index 843f81e..e4ce6f6 100644
--- a/src/SBaseFileTable.cpp
+++ b/src/SBaseFileTable.cpp
@@ -586,6 +586,9 @@ DWORD ConvertMpqHeaderToFormat4(
pHeader->BlockTableSize64 = (pHeader->dwBlockTableSize * sizeof(TMPQBlock));
BlockTablePos64 = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ // Supply the 64-bit archive size for signature verification
+ pHeader->ArchiveSize64 = pHeader->dwArchiveSize;
+
// We require the block table to follow hash table
if(BlockTablePos64 >= HashTablePos64)
{
@@ -600,7 +603,6 @@ DWORD ConvertMpqHeaderToFormat4(
}
else
{
- pHeader->ArchiveSize64 = pHeader->dwArchiveSize;
ha->dwFlags |= MPQ_FLAG_MALFORMED;
}
@@ -651,7 +653,7 @@ DWORD ConvertMpqHeaderToFormat4(
// Size of the block table
if(BlockTablePos64)
{
- if(BlockTablePos64 > FileSize)
+ if(BlockTablePos64 > FileSize || BlockTablePos64 >= MaxOffset)
return ERROR_FILE_CORRUPT;
pHeader->BlockTableSize64 = MaxOffset - BlockTablePos64;
MaxOffset = BlockTablePos64;
@@ -660,7 +662,7 @@ DWORD ConvertMpqHeaderToFormat4(
// Size of the hash table
if(HashTablePos64)
{
- if(HashTablePos64 > FileSize)
+ if(HashTablePos64 > FileSize || HashTablePos64 >= MaxOffset)
return ERROR_FILE_CORRUPT;
pHeader->HashTableSize64 = MaxOffset - HashTablePos64;
MaxOffset = HashTablePos64;
@@ -2560,12 +2562,7 @@ DWORD LoadAnyHashTable(TMPQArchive * ha)
// Note that we load the classic hash table even when HET table exists,
// because if the MPQ gets modified and saved, hash table must be there
if(pHeader->dwHashTableSize)
- {
- // hash-table size must be a power or 2
- if ((pHeader->dwHashTableSize & (pHeader->dwHashTableSize - 1)) != 0)
- return ERROR_FILE_CORRUPT;
ha->pHashTable = LoadHashTable(ha);
- }
// At least one of the tables must be present
if(ha->pHetTable == NULL && ha->pHashTable == NULL)
diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp
index 54dcbc5..f98a185 100644
--- a/src/SFileAddFile.cpp
+++ b/src/SFileAddFile.cpp
@@ -443,7 +443,7 @@ DWORD SFileAddFile_Init(
// Allocate the TMPQFile entry for newly added file
hf = CreateWritableHandle(ha, dwFileSize);
if(hf == NULL)
- return false;
+ return GetLastError();
// Allocate file entry in the MPQ
if(dwErrCode == ERROR_SUCCESS)
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index 180d428..f2c17ba 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -73,8 +73,8 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset,
// or not, we won't try that again for the given file.
//
- AllocateSectorChecksums(hf, true);
- hf->bLoadedSectorCRCs = true;
+ if(AllocateSectorChecksums(hf, true) == ERROR_SUCCESS)
+ hf->bLoadedSectorCRCs = true;
}
// TODO: If the raw data MD5s are not loaded yet, load them now
@@ -310,7 +310,7 @@ static DWORD ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFileP
// deDE\DBFilesClient\MountCapability.dbc 0x93->0x77 0x77 0x77 No
//
- if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
+ if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE && cbInBuffer > sizeof(TPatchInfo))
cbInBuffer = cbInBuffer - sizeof(TPatchInfo);
// Is the file compressed by Blizzard's multiple compression ?