diff options
| author | Zezula Ladislav <ladislav.zezula@avast.com> | 2018-10-15 11:23:52 +0200 | 
|---|---|---|
| committer | Zezula Ladislav <ladislav.zezula@avast.com> | 2018-10-15 11:23:52 +0200 | 
| commit | f35d106059accbddaa602b6525f9542746b2c2b7 (patch) | |
| tree | 4fd9212c6d57e430076dba99936b1503f18a8919 | |
| parent | 4ad0bff21da0163917e1552960e6a43679586b89 (diff) | |
+ Fixed arbitrarily large allocations caused by TQMPHeader::dwBlockTableSize
| -rw-r--r-- | StormLib_vs08.vcproj | 8 | ||||
| -rw-r--r-- | src/FileStream.cpp | 13 | ||||
| -rw-r--r-- | src/SBaseFileTable.cpp | 8 | ||||
| -rw-r--r-- | src/SFileOpenArchive.cpp | 1 | ||||
| -rw-r--r-- | src/SFileOpenFileEx.cpp | 5 | ||||
| -rw-r--r-- | test/StormTest.cpp | 30 | 
6 files changed, 50 insertions, 15 deletions
diff --git a/StormLib_vs08.vcproj b/StormLib_vs08.vcproj index db947a7..dce22e1 100644 --- a/StormLib_vs08.vcproj +++ b/StormLib_vs08.vcproj @@ -25,6 +25,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="2" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" @@ -88,6 +89,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="2" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" @@ -152,6 +154,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="2" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" @@ -215,6 +218,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="2" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" @@ -529,6 +533,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="1" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" @@ -592,6 +597,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="1" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" @@ -656,6 +662,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="1" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" @@ -719,6 +726,7 @@  			IntermediateDirectory="./bin/$(ProjectName)/$(PlatformName)/$(ConfigurationName)"  			ConfigurationType="4"  			CharacterSet="1" +			WholeProgramOptimization="0"  			>  			<Tool  				Name="VCPreBuildEventTool" diff --git a/src/FileStream.cpp b/src/FileStream.cpp index c73223c..84f36c0 100644 --- a/src/FileStream.cpp +++ b/src/FileStream.cpp @@ -652,6 +652,19 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD                      DWORD dwFileSize = 0;
                      DWORD dwDataSize;
                      DWORD dwIndex = 0;
 +                    TCHAR StatusCode[0x08];
 +
 +                    // Check if the file succeeded to open
 +                    dwDataSize = sizeof(StatusCode);
 +                    if(HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, StatusCode, &dwDataSize, &dwIndex))
 +                    {
 +                        if(_tcscmp(StatusCode, _T("200")))
 +                        {
 +                            InternetCloseHandle(hRequest);
 +                            SetLastError(ERROR_FILE_NOT_FOUND);
 +                            return false;
 +                        }
 +                    }
                      // Check if the MPQ has Last Modified field
                      dwDataSize = sizeof(ULONGLONG);
 diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 1cb469e..700df48 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -406,6 +406,14 @@ int ConvertMpqHeaderToFormat4(                  pHeader->ArchiveSize64 = DetermineArchiveSize_V1(ha, pHeader, MpqOffset, FileSize);
                  pHeader->dwArchiveSize = (DWORD)pHeader->ArchiveSize64;
              }
 +
 +            // EWIX_v8_7.w3x: TMPQHeader::dwBlockTableSize = 0x00319601
 +            // Size of TFileTable goes to ~200MB, so we artificially cut it
 +            if(BlockTablePos64 + (pHeader->dwBlockTableSize * sizeof(TMPQBlock)) > FileSize)
 +            {
 +                pHeader->dwBlockTableSize = (DWORD)((FileSize - BlockTablePos64) / sizeof(TMPQBlock));
 +                pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
 +            }
              break;
          case MPQ_FORMAT_VERSION_2:
 diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index a896eaf..15dffe4 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -118,7 +118,6 @@ static int VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize)      return ERROR_SUCCESS;  } -  /*****************************************************************************/  /* Public functions                                                          */  /*****************************************************************************/ diff --git a/src/SFileOpenFileEx.cpp b/src/SFileOpenFileEx.cpp index a25cc72..a139585 100644 --- a/src/SFileOpenFileEx.cpp +++ b/src/SFileOpenFileEx.cpp @@ -308,7 +308,10 @@ bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearch                  }              } -            nError = ERROR_FILE_NOT_FOUND; +            if(pFileEntry == NULL) +            { +                nError = ERROR_FILE_NOT_FOUND; +            }          }          // Ignore unknown loading flags (example: MPQ_2016_v1_WME4_4.w3x) diff --git a/test/StormTest.cpp b/test/StormTest.cpp index f1f6970..d248bd6 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -1611,7 +1611,8 @@ static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN          // Read the file data
          SFileReadFile(hFile, pFileData->FileData, dwFileSizeLo, &dwBytesRead, NULL);
          if(dwBytesRead != dwFileSizeLo)
 -            nError = pLogger->PrintError("Read failed: %s", szFileName);
 +//          nError = pLogger->PrintError("Read failed: %s", szFileName);
 +            nError = ERROR_FILE_CORRUPT;
      }
      // If failed, free the buffer
 @@ -2503,10 +2504,10 @@ static int TestOpenFile_OpenById(LPCTSTR szPlainName)  static int TestOpenFile_OpenByName(LPCTSTR szPlainName, LPCSTR szFileName)
  {
 -    TLogHelper Logger("OpenFileById", szPlainName);
 +    TLogHelper Logger("OpenFileByName", szPlainName);
      TFileData * pFileData = NULL;
 -    HANDLE hFile;
 -    HANDLE hMpq;
 +    HANDLE hFile = NULL;
 +    HANDLE hMpq = NULL;
      DWORD dwCrc32_1 = 0;
      DWORD dwCrc32_2 = 0;
      int nError;
 @@ -2541,11 +2542,11 @@ static int TestOpenFile_OpenByName(LPCTSTR szPlainName, LPCSTR szFileName)              if(dwCrc32_1 != dwCrc32_2)
                  Logger.PrintError("Warning: CRC32 error on %s", szFileName);
          }
 -    }
 -    // Close the archive
 -    if(hMpq != NULL)
 +        // Close the archive
          SFileCloseArchive(hMpq);
 +    }
 +
      return nError;
  }
 @@ -4462,11 +4463,11 @@ int _tmain(int argc, TCHAR * argv[])      // Open a stream, paired with local master
      if(nError == ERROR_SUCCESS)
          nError = TestReadFile_MasterMirror(_T("MPQ_2013_v4_alternate-complete.MPQ"), _T("MPQ_2013_v4_alternate-original.MPQ"), true);
 -
 +*/
      // Open a stream, paired with remote master (takes hell lot of time!!!)
      if(nError == ERROR_SUCCESS)
          nError = TestReadFile_MasterMirror(_T("MPQ_2013_v4_alternate-downloaded.MPQ"), _T("http://www.zezula.net\\mpqs\\alternate.zip"), false);
 -
 +/*
      // Search in listfile
      if(nError == ERROR_SUCCESS)
          nError = TestSearchListFile(_T("ListFile_Blizzard.txt"));
 @@ -4482,10 +4483,10 @@ int _tmain(int argc, TCHAR * argv[])      // Open the update MPQ from Diablo II (patch 2016)
      if(nError == ERROR_SUCCESS)
          nError = TestOpenFile_OpenByName(_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), "waitingroombkgd.dc6");
 -*/
 +
      if(nError == ERROR_SUCCESS)
          nError = TestOpenFile_OpenByName(_T("MPQ_2018_v1_icon_error.w3m"), "file00000002.blp");
 -/*
 +
      // Open a file whose archive's (signature) file has flags = 0x90000000
      if(nError == ERROR_SUCCESS)
          nError = TestOpenArchive(_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), _T("ListFile_Blizzard.txt"));
 @@ -4625,6 +4626,9 @@ int _tmain(int argc, TCHAR * argv[])      if(nError == ERROR_SUCCESS)
          nError = TestOpenArchive(_T("MPQ_2017_v1_TildeInFileName.mpq"), NULL, "1.blp");
 +    if(nError == ERROR_SUCCESS)
 +        nError = TestOpenArchive(_T("MPQ_2018_v1_EWIX_v8_7.w3x"), NULL, "BlueCrystal.mdx");
 +
      // Open the multi-file archive with wrong prefix to see how StormLib deals with it
      if(nError == ERROR_SUCCESS)
          nError = TestOpenArchive_WillFail(_T("flat-file://streaming/model.MPQ.0"));
 @@ -4696,7 +4700,7 @@ int _tmain(int argc, TCHAR * argv[])      // Check the SFileGetFileInfo function
      if(nError == ERROR_SUCCESS)
          nError = TestOpenArchive_GetFileInfo(_T("MPQ_2002_v1_StrongSignature.w3m"), _T("MPQ_2013_v4_SC2_EmptyMap.SC2Map"));
 -
 +*/
      // Downloadable MPQ archive
      if(nError == ERROR_SUCCESS)
          nError = TestOpenArchive_MasterMirror(_T("part-file://MPQ_2009_v1_patch-partial.MPQ.part"), _T("MPQ_2009_v1_patch-original.MPQ"), "world\\Azeroth\\DEADMINES\\PASSIVEDOODADS\\GOBLINMELTINGPOT\\DUST2.BLP", false);
 @@ -4835,7 +4839,7 @@ int _tmain(int argc, TCHAR * argv[])      // Test replacing a file with zero size file
      if(nError == ERROR_SUCCESS)
          nError = TestModifyArchive_ReplaceFile(_T("MPQ_2014_v4_Base.StormReplay"), _T("AddFile-replay.message.events"));
 -*/
 +
  #ifdef _MSC_VER
      _CrtDumpMemoryLeaks();
  #endif  // _MSC_VER
  | 
