diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/SBaseCommon.cpp | 4 | ||||
| -rw-r--r-- | src/SBaseFileTable.cpp | 46 | ||||
| -rw-r--r-- | src/SBaseSubTypes.cpp | 8 | ||||
| -rw-r--r-- | src/SFileFindFile.cpp | 2 | ||||
| -rw-r--r-- | src/SFileListFile.cpp | 2 | ||||
| -rw-r--r-- | src/SFileOpenArchive.cpp | 4 | ||||
| -rw-r--r-- | src/StormLib.h | 7 | 
7 files changed, 33 insertions, 40 deletions
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index 54fc6d0..95bdeb4 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -628,7 +628,7 @@ TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName)          TMPQHash * pHash = ha->pHashTable + dwIndex;
          // If the entry matches, we found it.
 -        if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex < ha->dwFileTableSize)
 +        if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
              return pHash;
          // If that hash entry is a free entry, it means we haven't found the file
 @@ -663,7 +663,7 @@ TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash *          pHash = ha->pHashTable + dwIndex;
          // If the entry matches, we found it.
 -        if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex < ha->dwFileTableSize)
 +        if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
              return pHash;
          // If that hash entry is a free entry, it means we haven't found the file
 diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 9d37ff1..981328b 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -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);
              }
          }
 diff --git a/src/SBaseSubTypes.cpp b/src/SBaseSubTypes.cpp index 9807701..1f72c17 100644 --- a/src/SBaseSubTypes.cpp +++ b/src/SBaseSubTypes.cpp @@ -187,7 +187,6 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)      TSQPHash * pSqpHashEnd;      TSQPHash * pSqpHash;      TMPQHash * pMpqHash; -    DWORD dwBlockIndex;      int nError = ERROR_SUCCESS;      // Load the hash table @@ -203,8 +202,7 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)              if(pSqpHash->dwBlockIndex != HASH_ENTRY_FREE)              {                  // Check block index against the size of the block table -                dwBlockIndex = pSqpHash->dwBlockIndex; -                if(pHeader->dwBlockTableSize <= dwBlockIndex && dwBlockIndex < HASH_ENTRY_DELETED) +                if(pHeader->dwBlockTableSize <= MPQ_BLOCK_INDEX(pSqpHash) && MPQ_BLOCK_INDEX(pSqpHash) < HASH_ENTRY_DELETED)                      nError = ERROR_FILE_CORRUPT;                  // We do not support nonzero locale and platform ID @@ -216,8 +214,8 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)                  pMpqHash->dwName2 = pSqpHash->dwName2;                  // Store the rest. Note that this must be done last, -                // because pSqpHash->dwBlockIndex corresponds to pMpqHash->dwName2 -                pMpqHash->dwBlockIndex = dwBlockIndex; +                // because block index corresponds to pMpqHash->dwName2 +                pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(pSqpHash);                  pMpqHash->wPlatform = 0;                  pMpqHash->lcLocale = 0;              } diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp index 41f31e1..18bf4d5 100644 --- a/src/SFileFindFile.cpp +++ b/src/SFileFindFile.cpp @@ -299,7 +299,7 @@ static int DoMPQSearch_HashTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileDa          if(IsValidHashEntry(ha, pHash))
          {
              // Check if this file entry should be included in the search result
 -            if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, pHash, ha->pFileTable + pHash->dwBlockIndex))
 +            if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, pHash, ha->pFileTable + MPQ_BLOCK_INDEX(pHash)))
                  return ERROR_SUCCESS;
          }
      }
 diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp index 62b8f11..3918bd9 100644 --- a/src/SFileListFile.cpp +++ b/src/SFileListFile.cpp @@ -350,7 +350,7 @@ static int SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szFil          while(pHash != NULL)
          {
              // Allocate file name for the file entry
 -            AllocateFileName(ha, ha->pFileTable + pHash->dwBlockIndex, szFileName);
 +            AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
              // Now find the next language version of the file
              pHash = GetNextHashEntry(ha, pFirstHash, pHash);
 diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index 2cb6698..62effe7 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -369,8 +369,8 @@ bool WINAPI SFileOpenArchive(          // higher than 0x10000000, it would overflow in 32-bit version          // Observed in the malformed Warcraft III maps          // Example map: MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x -        ha->pHeader->dwBlockTableSize = MPQ_BLOCK_INDEX(ha->pHeader->dwBlockTableSize); -        ha->pHeader->dwHashTableSize = MPQ_BLOCK_INDEX(ha->pHeader->dwHashTableSize); +        ha->pHeader->dwBlockTableSize = (ha->pHeader->dwBlockTableSize & BLOCK_INDEX_MASK); +        ha->pHeader->dwHashTableSize = (ha->pHeader->dwHashTableSize & BLOCK_INDEX_MASK);          // Both MPQ_OPEN_NO_LISTFILE or MPQ_OPEN_NO_ATTRIBUTES trigger read only mode          if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES)) diff --git a/src/StormLib.h b/src/StormLib.h index c25a1a8..3621096 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -230,7 +230,12 @@ extern "C" {                                    MPQ_FILE_SIGNATURE     |  \                                    MPQ_FILE_EXISTS) -#define MPQ_BLOCK_INDEX(bi) ((bi) & 0x0FFFFFFF) // Index mask for block table index +// 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 << 0x04 +// Malformed MPQ maps may contain block indexes like 0x40000001 or 0xF0000023 +#define BLOCK_INDEX_MASK          0x0FFFFFFF +#define MPQ_BLOCK_INDEX(pHash) (pHash->dwBlockIndex & BLOCK_INDEX_MASK)  // Compression types for multiple compressions  #define MPQ_COMPRESSION_HUFFMANN          0x01  // Huffmann compression (used on WAVE files only)  | 
