summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLadislav Zezula <ladislav.zezula@avg.com>2015-05-28 13:49:23 +0200
committerLadislav Zezula <ladislav.zezula@avg.com>2015-05-28 13:49:23 +0200
commit1b38ceb0d4bb4ae32cb93c295e3ef493b91f9a78 (patch)
tree5634e1d3fd17386975db1c0d4e95176db098bc1f
parentc26e12c79f2a5e0c092de4a62565bdae4bf5a7dd (diff)
+ Fixed defects found by Coverity (well, most of them)
-rw-r--r--src/FileStream.cpp24
-rw-r--r--src/SBaseCommon.cpp51
-rw-r--r--src/SBaseFileTable.cpp28
-rw-r--r--src/SCompression.cpp7
-rw-r--r--src/SFileAddFile.cpp31
-rw-r--r--src/SFileAttributes.cpp30
-rw-r--r--src/SFileCompactArchive.cpp12
-rw-r--r--src/SFileFindFile.cpp8
-rw-r--r--src/SFileListFile.cpp2
-rw-r--r--src/SFileOpenArchive.cpp27
-rw-r--r--src/SFilePatchArchives.cpp3
-rw-r--r--src/SFileReadFile.cpp10
-rw-r--r--src/StormCommon.h9
-rw-r--r--src/adpcm/adpcm.cpp2
-rw-r--r--src/huffman/huff.cpp8
-rw-r--r--src/huffman/huff.h2
-rw-r--r--src/pklib/explode.c2
-rw-r--r--src/pklib/implode.c2
-rw-r--r--src/sparse/sparse.cpp14
-rw-r--r--test/StormTest.cpp97
20 files changed, 233 insertions, 136 deletions
diff --git a/src/FileStream.cpp b/src/FileStream.cpp
index 53740fa..a367db6 100644
--- a/src/FileStream.cpp
+++ b/src/FileStream.cpp
@@ -618,19 +618,16 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
// Don't connect to the internet
if(!InternetGetConnectedState(&dwTemp, 0))
- nError = GetLastError();
+ return false;
// Initiate the connection to the internet
- if(nError == ERROR_SUCCESS)
- {
- pStream->Base.Http.hInternet = InternetOpen(_T("StormLib HTTP MPQ reader"),
- INTERNET_OPEN_TYPE_PRECONFIG,
- NULL,
- NULL,
- 0);
- if(pStream->Base.Http.hInternet == NULL)
- nError = GetLastError();
- }
+ pStream->Base.Http.hInternet = InternetOpen(_T("StormLib HTTP MPQ reader"),
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL,
+ NULL,
+ 0);
+ if(pStream->Base.Http.hInternet == NULL)
+ return false;
// Connect to the server
if(nError == ERROR_SUCCESS)
@@ -649,7 +646,10 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
dwFlags,
0);
if(pStream->Base.Http.hConnect == NULL)
- nError = GetLastError();
+ {
+ InternetCloseHandle(pStream->Base.Http.hInternet);
+ return false;
+ }
}
// Now try to query the file size
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp
index 9ae7c78..b16472e 100644
--- a/src/SBaseCommon.cpp
+++ b/src/SBaseCommon.cpp
@@ -93,6 +93,57 @@ unsigned char AsciiToUpperTable_Slash[256] =
};
//-----------------------------------------------------------------------------
+// Safe string functions
+
+void StringCopyA(char * dest, const char * src, size_t nMaxChars)
+{
+ size_t nLength = strlen(src);
+
+ // Don't copy more than nMaxChars
+ nLength = STORMLIB_MIN(nLength, nMaxChars);
+ memcpy(dest, src, nLength);
+ dest[nLength] = 0;
+}
+
+void StringCatA(char * dest, const char * src, size_t nMaxChars)
+{
+ size_t nLength1 = strlen(dest);
+ size_t nLength2 = strlen(src);
+
+ // Don't copy more than nMaxChars
+ if(nLength1 < nMaxChars)
+ {
+ nLength2 = STORMLIB_MIN(nLength2, (nMaxChars - nLength1));
+ memcpy(dest + nLength1, src, nLength2);
+ dest[nLength1 + nLength2] = 0;
+ }
+}
+
+void StringCopyT(TCHAR * dest, const TCHAR * src, size_t nMaxChars)
+{
+ size_t nLength = _tcslen(src);
+
+ // Don't copy more than nMaxChars
+ nLength = STORMLIB_MIN(nLength, nMaxChars);
+ memcpy(dest, src, (nLength * sizeof(TCHAR)));
+ dest[nLength] = 0;
+}
+
+void StringCatT(TCHAR * dest, const TCHAR * src, size_t nMaxChars)
+{
+ size_t nLength1 = _tcslen(dest);
+ size_t nLength2 = _tcslen(src);
+
+ // Don't copy more than nMaxChars
+ if(nLength1 < nMaxChars)
+ {
+ nLength2 = STORMLIB_MIN(nLength2, (nMaxChars - nLength1));
+ memcpy(dest + nLength1, src, (nLength2 * sizeof(TCHAR)));
+ dest[nLength1 + nLength2] = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
// Storm hashing functions
#define STORM_BUFFER_SIZE 0x500
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp
index fbe10ee..1a1e8ee 100644
--- a/src/SBaseFileTable.cpp
+++ b/src/SBaseFileTable.cpp
@@ -247,9 +247,11 @@ static ULONGLONG DetermineArchiveSize_V1(
if((EndOfMpq - MpqOffset) > (MPQ_STRONG_SIGNATURE_SIZE + 4))
{
ByteOffset = EndOfMpq - MPQ_STRONG_SIGNATURE_SIZE - 4;
- FileStream_Read(ha->pStream, &ByteOffset, &SignatureHeader, sizeof(DWORD));
- if(BSWAP_INT32_UNSIGNED(SignatureHeader) == MPQ_STRONG_SIGNATURE_ID)
- EndOfMpq = EndOfMpq - MPQ_STRONG_SIGNATURE_SIZE - 4;
+ if(FileStream_Read(ha->pStream, &ByteOffset, &SignatureHeader, sizeof(DWORD)))
+ {
+ if(BSWAP_INT32_UNSIGNED(SignatureHeader) == MPQ_STRONG_SIGNATURE_ID)
+ EndOfMpq = EndOfMpq - MPQ_STRONG_SIGNATURE_SIZE - 4;
+ }
}
// Return the returned archive size
@@ -1359,6 +1361,9 @@ static TMPQExtHeader * TranslateHetTable(TMPQHetTable * pHetTable, ULONGLONG * p
{
*pcbHetTable = (ULONGLONG)(sizeof(TMPQExtHeader) + HetHeader.dwTableSize);
}
+
+ // Free the linear table
+ STORM_FREE(pbLinearTable);
}
return &pHetHeader->ExtHdr;
@@ -1549,7 +1554,7 @@ static TMPQBetTable * TranslateBetTable(
{
TMPQBetTable * pBetTable = NULL;
LPBYTE pbSrcData = (LPBYTE)(pBetHeader + 1);
- DWORD LengthInBytes;
+ DWORD LengthInBytes = 0;
// Sanity check
assert(pBetHeader->ExtHdr.dwSignature == BET_TABLE_SIGNATURE);
@@ -1610,10 +1615,12 @@ static TMPQBetTable * TranslateBetTable(
// Load the bit-based file table
pBetTable->pFileTable = CreateBitArray(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0);
- LengthInBytes = (pBetTable->pFileTable->NumberOfBits + 7) / 8;
if(pBetTable->pFileTable != NULL)
+ {
+ LengthInBytes = (pBetTable->pFileTable->NumberOfBits + 7) / 8;
memcpy(pBetTable->pFileTable->Elements, pbSrcData, LengthInBytes);
- pbSrcData += LengthInBytes;
+ pbSrcData += LengthInBytes;
+ }
// Fill the sizes of BET hash
pBetTable->dwBitTotal_NameHash2 = pBetHeader->dwBitTotal_NameHash2;
@@ -1622,10 +1629,12 @@ static TMPQBetTable * TranslateBetTable(
// Create and load the array of BET hashes
pBetTable->pNameHashes = CreateBitArray(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0);
- LengthInBytes = (pBetTable->pNameHashes->NumberOfBits + 7) / 8;
if(pBetTable->pNameHashes != NULL)
+ {
+ LengthInBytes = (pBetTable->pNameHashes->NumberOfBits + 7) / 8;
memcpy(pBetTable->pNameHashes->Elements, pbSrcData, LengthInBytes);
-// pbSrcData += pBetHeader->dwNameHashArraySize;
+// pbSrcData += LengthInBytes;
+ }
// Dump both tables
// DumpHetAndBetTable(ha->pHetTable, pBetTable);
@@ -2387,7 +2396,10 @@ static int BuildFileTable_HetBet(TMPQArchive * ha)
// Verify the size of NameHash2 in the BET table.
// It has to be 8 bits less than the information in HET table
if((pBetTable->dwBitCount_NameHash2 + 8) != pHetTable->dwNameHashBitSize)
+ {
+ FreeBetTable(pBetTable);
return ERROR_FILE_CORRUPT;
+ }
// Step one: Fill the name indexes
for(i = 0; i < pHetTable->dwTotalCount; i++)
diff --git a/src/SCompression.cpp b/src/SCompression.cpp
index 5402771..d706a6f 100644
--- a/src/SCompression.cpp
+++ b/src/SCompression.cpp
@@ -296,7 +296,10 @@ static int Decompress_PKLIB(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB
// If PKLIB is unable to decompress the data, return 0;
if(Info.pbOutBuff == pvOutBuffer)
+ {
+ STORM_FREE(work_buf);
return 0;
+ }
// Give away the number of decompressed bytes
*pcbOutBuffer = (int)(Info.pbOutBuff - (unsigned char *)pvOutBuffer);
@@ -324,6 +327,7 @@ static void Compress_BZIP2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu
// Initialize the BZIP2 compression
strm.bzalloc = NULL;
strm.bzfree = NULL;
+ strm.opaque = NULL;
// Blizzard uses 9 as blockSize100k, (0x30 as workFactor)
// Last checked on Starcraft II
@@ -358,6 +362,9 @@ static int Decompress_BZIP2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB
// Initialize the BZIP2 decompression
strm.bzalloc = NULL;
strm.bzfree = NULL;
+ strm.opaque = NULL;
+
+ // Initialize decompression
if(BZ2_bzDecompressInit(&strm, 0, 0) == BZ_OK)
{
strm.next_in = (char *)pvInBuffer;
diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp
index ea3c5f9..b70eeb1 100644
--- a/src/SFileAddFile.cpp
+++ b/src/SFileAddFile.cpp
@@ -435,7 +435,7 @@ int SFileAddFile_Init(
// Allocate the TMPQFile entry for newly added file
hf = CreateWritableHandle(ha, dwFileSize);
if(hf == NULL)
- nError = GetLastError();
+ return false;
// Allocate file entry in the MPQ
if(nError == ERROR_SUCCESS)
@@ -902,26 +902,21 @@ bool WINAPI SFileAddFileEx(
// Check parameters
if(hMpq == NULL || szFileName == NULL || *szFileName == 0)
- nError = ERROR_INVALID_PARAMETER;
-
- // Open added file
- if(nError == ERROR_SUCCESS)
{
- pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
- if(pStream == NULL)
- nError = GetLastError();
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
}
- // Get the file size and file time
- if(nError == ERROR_SUCCESS)
- {
- FileStream_GetTime(pStream, &FileTime);
- FileStream_GetSize(pStream, &FileSize);
-
- // Files bigger than 4GB cannot be added to MPQ
- if(FileSize >> 32)
- nError = ERROR_DISK_FULL;
- }
+ // Open added file
+ pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
+ if(pStream == NULL)
+ return false;
+
+ // Files bigger than 4GB cannot be added to MPQ
+ FileStream_GetTime(pStream, &FileTime);
+ FileStream_GetSize(pStream, &FileSize);
+ if(FileSize >> 32)
+ nError = ERROR_DISK_FULL;
// Allocate data buffer for reading from the source file
if(nError == ERROR_SUCCESS)
diff --git a/src/SFileAttributes.cpp b/src/SFileAttributes.cpp
index d37d83c..dc13b2c 100644
--- a/src/SFileAttributes.cpp
+++ b/src/SFileAttributes.cpp
@@ -378,22 +378,26 @@ int SAttrLoadAttributes(TMPQArchive * ha)
{
// Retrieve and check size of the (attributes) file
cbAttrFile = SFileGetFileSize(hFile, NULL);
-
- // Size of the (attributes) might be 1 byte less than expected
- // See GetSizeOfAttributesFile for more info
- pbAttrFile = STORM_ALLOC(BYTE, cbAttrFile + 1);
- if(pbAttrFile != NULL)
+
+ // Integer overflow check
+ if((cbAttrFile + 1) > cbAttrFile)
{
- // Set the last byte to 0 in case the size should be 1 byte greater
- pbAttrFile[cbAttrFile] = 0;
+ // Size of the (attributes) might be 1 byte less than expected
+ // See GetSizeOfAttributesFile for more info
+ pbAttrFile = STORM_ALLOC(BYTE, cbAttrFile + 1);
+ if(pbAttrFile != NULL)
+ {
+ // Set the last byte to 0 in case the size should be 1 byte greater
+ pbAttrFile[cbAttrFile] = 0;
- // Load the entire file to memory
- SFileReadFile(hFile, pbAttrFile, cbAttrFile, &dwBytesRead, NULL);
- if(dwBytesRead == cbAttrFile)
- nError = LoadAttributesFile(ha, pbAttrFile, cbAttrFile);
+ // Load the entire file to memory
+ SFileReadFile(hFile, pbAttrFile, cbAttrFile, &dwBytesRead, NULL);
+ if(dwBytesRead == cbAttrFile)
+ nError = LoadAttributesFile(ha, pbAttrFile, cbAttrFile);
- // Free the buffer
- STORM_FREE(pbAttrFile);
+ // Free the buffer
+ STORM_FREE(pbAttrFile);
+ }
}
// Close the attributes file
diff --git a/src/SFileCompactArchive.cpp b/src/SFileCompactArchive.cpp
index be1ca66..5b6cbe3 100644
--- a/src/SFileCompactArchive.cpp
+++ b/src/SFileCompactArchive.cpp
@@ -530,8 +530,7 @@ bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile, bool /* bR
ULONGLONG ByteOffset;
ULONGLONG ByteCount;
LPDWORD pFileKeys = NULL;
- TCHAR szTempFile[MAX_PATH] = _T("");
- TCHAR * szTemp = NULL;
+ TCHAR szTempFile[MAX_PATH+1] = _T("");
int nError = ERROR_SUCCESS;
// Test the valid parameters
@@ -568,12 +567,11 @@ bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile, bool /* bR
// Get the temporary file name and create it
if(nError == ERROR_SUCCESS)
{
- _tcscpy(szTempFile, FileStream_GetFileName(ha->pStream));
- if((szTemp = _tcsrchr(szTempFile, '.')) != NULL)
- _tcscpy(szTemp + 1, _T("mp_"));
- else
- _tcscat(szTempFile, _T("_"));
+ // Create temporary file name. Prevent buffer overflow
+ StringCopyT(szTempFile, FileStream_GetFileName(ha->pStream), MAX_PATH);
+ StringCatT(szTempFile, _T(".tmp"), MAX_PATH);
+ // Create temporary file
pTempStream = FileStream_CreateFile(szTempFile, STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
if(pTempStream == NULL)
nError = GetLastError();
diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp
index 3d6c74e..3e6854b 100644
--- a/src/SFileFindFile.cpp
+++ b/src/SFileFindFile.cpp
@@ -185,7 +185,7 @@ static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry)
{
TFileEntry * pPatchEntry = NULL;
TFileEntry * pTempEntry;
- char szFileName[MAX_PATH];
+ char szFileName[MAX_PATH+1];
// Go while there are patches
while(ha->haPatch != NULL)
@@ -196,8 +196,8 @@ static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry)
// Prepare the prefix for the file name
if(ha->pPatchPrefix != NULL)
- strcpy(szFileName, ha->pPatchPrefix->szPatchPrefix);
- strcat(szFileName, pFileEntry->szFileName);
+ StringCopyA(szFileName, ha->pPatchPrefix->szPatchPrefix, MAX_PATH);
+ StringCatA(szFileName, pFileEntry->szFileName, MAX_PATH);
// Try to find the file there
pTempEntry = GetFileEntryExact(ha, szFileName, 0, NULL);
@@ -280,7 +280,7 @@ static bool DoMPQSearch_FileEntry(
}
// Fill the file name and plain file name
- strcpy(lpFindFileData->cFileName, szFileName + nPrefixLength);
+ StringCopyA(lpFindFileData->cFileName, szFileName + nPrefixLength, MAX_PATH-1);
lpFindFileData->szPlainName = (char *)GetPlainFileName(lpFindFileData->cFileName);
return true;
}
diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp
index 7919475..e47a9ea 100644
--- a/src/SFileListFile.cpp
+++ b/src/SFileListFile.cpp
@@ -543,7 +543,7 @@ static bool DoListFileSearch(TListFileCache * pCache, SFILE_FIND_DATA * lpFindFi
if(nLength != 0 && CheckWildCard(szFileName, pCache->szWildCard))
{
if(nLength >= sizeof(lpFindFileData->cFileName))
- nLength = sizeof(lpFindFileData->cFileName);
+ nLength = sizeof(lpFindFileData->cFileName) - 1;
memcpy(lpFindFileData->cFileName, szFileName, nLength);
lpFindFileData->cFileName[nLength] = 0;
diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp
index 35fd4dd..d62b98f 100644
--- a/src/SFileOpenArchive.cpp
+++ b/src/SFileOpenArchive.cpp
@@ -158,30 +158,28 @@ bool WINAPI SFileOpenArchive(
TFileEntry * pFileEntry;
ULONGLONG FileSize = 0; // Size of the file
LPBYTE pbHeaderBuffer = NULL; // Buffer for searching MPQ header
+ DWORD dwStreamFlags = (dwFlags & STREAM_FLAGS_MASK);
bool bIsWarcraft3Map = false;
int nError = ERROR_SUCCESS;
// Verify the parameters
if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
- nError = ERROR_INVALID_PARAMETER;
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
// One time initialization of MPQ cryptography
InitializeMpqCryptography();
dwPriority = dwPriority;
- // Open the MPQ archive file
- if(nError == ERROR_SUCCESS)
- {
- DWORD dwStreamFlags = (dwFlags & STREAM_FLAGS_MASK);
-
- // If not forcing MPQ v 1.0, also use file bitmap
- dwStreamFlags |= (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) ? 0 : STREAM_FLAG_USE_BITMAP;
+ // If not forcing MPQ v 1.0, also use file bitmap
+ dwStreamFlags |= (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) ? 0 : STREAM_FLAG_USE_BITMAP;
- // Initialize the stream
- pStream = FileStream_OpenFile(szMpqName, dwStreamFlags);
- if(pStream == NULL)
- nError = GetLastError();
- }
+ // Open the MPQ archive file
+ pStream = FileStream_OpenFile(szMpqName, dwStreamFlags);
+ if(pStream == NULL)
+ return false;
// Check the file size. There must be at least 0x20 bytes
if(nError == ERROR_SUCCESS)
@@ -450,7 +448,8 @@ bool WINAPI SFileOpenArchive(
// Free the header buffer
if(pbHeaderBuffer != NULL)
STORM_FREE(pbHeaderBuffer);
- *phMpq = ha;
+ if(phMpq != NULL)
+ *phMpq = ha;
return (nError == ERROR_SUCCESS);
}
diff --git a/src/SFilePatchArchives.cpp b/src/SFilePatchArchives.cpp
index f4867b0..9cb6ecd 100644
--- a/src/SFilePatchArchives.cpp
+++ b/src/SFilePatchArchives.cpp
@@ -589,7 +589,10 @@ static bool FindPatchPrefix_SC2(TMPQArchive * haBase, TMPQArchive * haPatch)
// Find a *-md5.lst file in the base archive
pBaseEntry = FindBaseLstFile(haBase);
if(pBaseEntry == NULL)
+ {
+ STORM_FREE(szLstFileName);
return false;
+ }
// Parse the entire file table
for(pFileEntry = haPatch->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index d81b4de..5d64626 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -54,7 +54,7 @@ static int ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, DW
if(hf->SectorOffsets == NULL)
{
nError = AllocateSectorOffsets(hf, true);
- if(nError != ERROR_SUCCESS)
+ if(nError != ERROR_SUCCESS || hf->SectorOffsets == NULL)
return nError;
}
@@ -231,7 +231,7 @@ static int ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos
if(hf->pbFileSector == NULL)
{
nError = AllocateSectorBuffer(hf);
- if(nError != ERROR_SUCCESS)
+ if(nError != ERROR_SUCCESS || hf->pbFileSector == NULL)
return nError;
pbRawData = hf->pbFileSector;
}
@@ -367,7 +367,7 @@ static int ReadMpkFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos
if(hf->pbFileSector == NULL)
{
nError = AllocateSectorBuffer(hf);
- if(nError != ERROR_SUCCESS)
+ if(nError != ERROR_SUCCESS || hf->pbFileSector == NULL)
return nError;
pbRawData = hf->pbFileSector;
}
@@ -477,7 +477,7 @@ static int ReadMpqFileSectorFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos
if(hf->pbFileSector == NULL)
{
nError = AllocateSectorBuffer(hf);
- if(nError != ERROR_SUCCESS)
+ if(nError != ERROR_SUCCESS || hf->pbFileSector == NULL)
return nError;
}
@@ -690,7 +690,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
if(hf->pFileEntry != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) && hf->pPatchInfo == NULL)
{
nError = AllocatePatchInfo(hf, true);
- if(nError != ERROR_SUCCESS)
+ if(nError != ERROR_SUCCESS || hf->pPatchInfo == NULL)
{
SetLastError(nError);
return false;
diff --git a/src/StormCommon.h b/src/StormCommon.h
index d4bf57c..0b1ccb2 100644
--- a/src/StormCommon.h
+++ b/src/StormCommon.h
@@ -131,6 +131,15 @@ extern unsigned char AsciiToLowerTable[256];
extern unsigned char AsciiToUpperTable[256];
//-----------------------------------------------------------------------------
+// Safe string functions
+
+void StringCopyA(char * dest, const char * src, size_t nMaxChars);
+void StringCatA(char * dest, const char * src, size_t nMaxChars);
+
+void StringCopyT(TCHAR * dest, const TCHAR * src, size_t nMaxChars);
+void StringCatT(TCHAR * dest, const TCHAR * src, size_t nMaxChars);
+
+//-----------------------------------------------------------------------------
// Encryption and decryption functions
#define MPQ_HASH_TABLE_INDEX 0x000
diff --git a/src/adpcm/adpcm.cpp b/src/adpcm/adpcm.cpp
index 7805dc5..e3741b6 100644
--- a/src/adpcm/adpcm.cpp
+++ b/src/adpcm/adpcm.cpp
@@ -194,6 +194,7 @@ int CompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cb
return 2;
// Set the initial step index for each channel
+ PredictedSamples[0] = PredictedSamples[1] = 0;
StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX;
// Next, InitialSample value for each channel follows
@@ -306,6 +307,7 @@ int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int
int ChannelIndex; // Current channel index
// Initialize the StepIndex for each channel
+ PredictedSamples[0] = PredictedSamples[1] = 0;
StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX;
// _tprintf(_T("== DCMP Started ==============\n"));
diff --git a/src/huffman/huff.cpp b/src/huffman/huff.cpp
index c973580..1636a80 100644
--- a/src/huffman/huff.cpp
+++ b/src/huffman/huff.cpp
@@ -409,7 +409,10 @@ THuffmannTree::THuffmannTree(bool bCompression)
pFirst = pLast = LIST_HEAD();
MinValidValue = 1;
ItemsUsed = 0;
-
+ bIsCmp0 = 0;
+
+ memset(ItemsByByte, 0, sizeof(ItemsByByte));
+
// If we are going to decompress data, we need to invalidate all item links
// We do so by zeroing their ValidValue, so it becomes lower MinValidValue
if(bCompression == false)
@@ -737,7 +740,8 @@ unsigned int THuffmannTree::DecodeOneByte(TInputStream * is)
else
{
// Limit the quick-decompress item to lower amount of bits
- ItemLinkIndex &= (0xFFFFFFFF >> (32 - BitCount));
+ // Coverity fix 84457: (x >> 32) has undefined behavior
+ ItemLinkIndex = (BitCount != 0) ? ItemLinkIndex & (0xFFFFFFFF >> (32 - BitCount)) : 0;
while(ItemLinkIndex < LINK_ITEM_COUNT)
{
// Fill the quick-decompress item
diff --git a/src/huffman/huff.h b/src/huffman/huff.h
index b0a54ee..2bd5abc 100644
--- a/src/huffman/huff.h
+++ b/src/huffman/huff.h
@@ -67,7 +67,7 @@ enum TInsertPoint
// Huffmann tree item
struct THTreeItem
{
- THTreeItem() { pPrev = pNext = NULL;}
+ THTreeItem() { pPrev = pNext = NULL; DecompressedValue = 0; Weight = 0; pParent = pChildLo = NULL; }
// ~THTreeItem() { RemoveItem(); }
void RemoveItem();
diff --git a/src/pklib/explode.c b/src/pklib/explode.c
index 73c5004..9796173 100644
--- a/src/pklib/explode.c
+++ b/src/pklib/explode.c
@@ -455,7 +455,7 @@ static unsigned int Expand(TDcmpStruct * pWork)
// Note that if the output buffer overflowed previously, the extra decompressed bytes
// are stored in "out_buff_overflow", and they will now be
// within decompressed part of the output buffer.
- memcpy(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
+ memmove(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
pWork->outputPos -= 0x1000;
}
}
diff --git a/src/pklib/implode.c b/src/pklib/implode.c
index 1771b18..f29f54d 100644
--- a/src/pklib/implode.c
+++ b/src/pklib/implode.c
@@ -662,7 +662,7 @@ _00402252:;
if(input_data_ended == 0)
{
input_data -= 0x1000;
- memcpy(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + 0x204);
+ memmove(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + 0x204);
}
}
diff --git a/src/sparse/sparse.cpp b/src/sparse/sparse.cpp
index dc988ba..4fe0981 100644
--- a/src/sparse/sparse.cpp
+++ b/src/sparse/sparse.cpp
@@ -130,20 +130,6 @@ void CompressSparse(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, i
pbOutBuffer += NumberOfNonZeros;
pbInBuffer += NumberOfNonZeros;
}
- else
- {
- // Verify if we still have enough space in output buffer
- if((pbOutBuffer + 2) >= pbOutBufferEnd)
- return;
-
- // Put marker that means "1 nonzero byte"
- *pbOutBuffer++ = 0x80;
- memcpy(pbOutBuffer, pbInBuffer, 1);
-
- // Adjust pointers
- pbOutBuffer++;
- pbInBuffer++;
- }
}
// Now flush all zero bytes
diff --git a/test/StormTest.cpp b/test/StormTest.cpp
index 26188ae..192c5d4 100644
--- a/test/StormTest.cpp
+++ b/test/StormTest.cpp
@@ -241,7 +241,7 @@ static const char * PatchList_HS_6898_enGB[] =
// This must be the directory where our test MPQs are stored.
// We also expect a subdirectory named
-static char szMpqDirectory[MAX_PATH];
+static char szMpqDirectory[MAX_PATH+1];
size_t cchMpqDirectory = 0;
static bool IsFullPath(const char * szFileName)
@@ -890,7 +890,7 @@ static int InitializeMpqDirectory(char * argv[], int argc)
}
// Copy the name of the MPQ directory.
- strcpy(szMpqDirectory, szDirName);
+ StringCopyA(szMpqDirectory, szDirName, MAX_PATH);
cchMpqDirectory = strlen(szMpqDirectory);
// Cut trailing slashes and/or backslashes
@@ -1777,13 +1777,13 @@ static int CreateNewArchiveU(TLogHelper * pLogger, const wchar_t * szPlainName,
{
#ifdef _UNICODE
HANDLE hMpq = NULL;
- TCHAR szMpqName[MAX_PATH];
+ TCHAR szMpqName[MAX_PATH+1];
char szFullPath[MAX_PATH];
// Construct the full UNICODE name
CreateFullPathName(szFullPath, NULL, "StormLibTest_");
CopyFileName(szMpqName, szFullPath, strlen(szFullPath));
- wcscat(szMpqName, szPlainName);
+ StringCatT(szMpqName, szPlainName, MAX_PATH);
// Make sure that the MPQ is deleted
_tremove(szMpqName);
@@ -1825,16 +1825,17 @@ static int OpenExistingArchive(TLogHelper * pLogger, const char * szFullPath, DW
CopyFileName(szMpqName, szFullPath, strlen(szFullPath));
if(!SFileOpenArchive(szMpqName, 0, dwFlags, &hMpq))
{
- // If the error is ERROR_BAD_FORMAT, try to open with MPQ_OPEN_FORCE_MPQ_V1
-// if((nError = GetLastError()) == ERROR_BAD_FORMAT)
-// {
-// bReopenResult = SFileOpenArchive(szMpqName, 0, dwFlags | MPQ_OPEN_FORCE_MPQ_V1, &hMpq);
-// nError = (bReopenResult == false) ? GetLastError() : ERROR_SUCCESS;
-// }
-
- // Ignore the error if it's an AVI file or if the file is incomplete
- if(nError == ERROR_AVI_FILE || nError == ERROR_FILE_INCOMPLETE)
- return nError;
+ switch(nError = GetLastError())
+ {
+// case ERROR_BAD_FORMAT: // If the error is ERROR_BAD_FORMAT, try to open with MPQ_OPEN_FORCE_MPQ_V1
+// bReopenResult = SFileOpenArchive(szMpqName, 0, dwFlags | MPQ_OPEN_FORCE_MPQ_V1, &hMpq);
+// nError = (bReopenResult == false) ? GetLastError() : ERROR_SUCCESS;
+// break;
+
+ case ERROR_AVI_FILE: // Ignore the error if it's an AVI file or if the file is incomplete
+ case ERROR_FILE_INCOMPLETE:
+ return nError;
+ }
// Show the open error to the user
return pLogger->PrintError("Failed to open archive %s", szFullPath);
@@ -2201,6 +2202,31 @@ static int TestReadFile_MasterMirror(const char * szMirrorName, const char * szM
}
// Test of the TFileStream object
+static int TestSparseCompression()
+{
+ BYTE InpBuffer[0x1000];
+ BYTE Compressed[0x1000];
+ BYTE Decompressed[0x1000];
+ int cbCompressed = sizeof(Compressed);
+ int cbDecompressed = sizeof(Compressed);
+
+ // Prepare compressed buffer
+ memset(InpBuffer, 0, sizeof(InpBuffer));
+
+ // Compress and decompress
+ CompressSparse(Compressed, &cbCompressed, InpBuffer, sizeof(InpBuffer));
+ DecompressSparse(Decompressed, &cbDecompressed, Compressed, cbCompressed);
+
+ // Check the result of decompression
+ if(cbDecompressed != sizeof(InpBuffer))
+ return ERROR_FILE_CORRUPT;
+ if(memcmp(Decompressed, InpBuffer, sizeof(InpBuffer)))
+ return ERROR_FILE_CORRUPT;
+
+ return ERROR_SUCCESS;
+}
+
+// Test of the TFileStream object
static int TestFileStreamOperations(const char * szPlainName, DWORD dwStreamFlags)
{
TFileStream * pStream = NULL;
@@ -2223,7 +2249,7 @@ static int TestFileStreamOperations(const char * szPlainName, DWORD dwStreamFlag
{
pStream = FileStream_OpenFileA(szFullPath, dwStreamFlags);
if(pStream == NULL)
- nError = Logger.PrintError("Failed to open %s", szFullPath);
+ return Logger.PrintError("Failed to open %s", szFullPath);
}
// Get the size of the file stream
@@ -2917,12 +2943,12 @@ static int ForEachFile_VerifyFileChecksum(const char * szFullPath)
const char * szShortPlainName = GetShortPlainName(szFullPath);
TFileData * pFileData;
char * szExtension;
- char szShaFileName[MAX_PATH];
+ char szShaFileName[MAX_PATH+1];
char szSha1Text[0x40];
int nError = ERROR_SUCCESS;
// Try to load the file with the SHA extension
- strcpy(szShaFileName, szFullPath);
+ StringCopyA(szShaFileName, szFullPath, MAX_PATH);
szExtension = strrchr(szShaFileName, '.');
if(szExtension == NULL)
return ERROR_SUCCESS;
@@ -2993,16 +3019,16 @@ static int ForEachFile_OpenArchive(const char * szFullPath)
// Adding a file to MPQ that had size of the file table equal
// or greater than hash table, but has free entries
-static int TestAddFile_FullTable(const char * szFullMpq1, const char * szFullMpq2)
+static int TestAddFile_FullTable(const char * szFullMpqName)
{
- TLogHelper Logger("FullMpqTest", szFullMpq1);
+ TLogHelper Logger("FullMpqTest", szFullMpqName);
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, szFullMpq1, szFullMpq1, &hMpq);
+ nError = OpenExistingArchiveWithCopy(&Logger, szFullMpqName, szFullMpqName, &hMpq);
if(nError == ERROR_SUCCESS)
{
// Attempt to add a file
@@ -3010,15 +3036,6 @@ static int TestAddFile_FullTable(const char * szFullMpq1, const char * szFullMpq
SFileCloseArchive(hMpq);
}
- // Copy the archive so we won't fuck up the original one
- nError = OpenExistingArchiveWithCopy(&Logger, szFullMpq2, szFullMpq2, &hMpq);
- if(nError == ERROR_SUCCESS)
- {
- // Now add a file
- nError = AddFileToMpq(&Logger, hMpq, szFileName, szFileData, MPQ_FILE_IMPLODE, MPQ_COMPRESSION_PKWARE, ERROR_SUCCESS);
- SFileCloseArchive(hMpq);
- }
-
return nError;
}
@@ -3994,6 +4011,7 @@ static int CreateArchiveLinkFile(const char * szFullPath1, const char * szFullPa
char szLinkFile[MAX_PATH];
char szLinkPath[MAX_PATH];
int nLength;
+ int nError = ERROR_SUCCESS;
// Construct the link file name
CalculateRelativePath(szFullPath1, szFullPath2, szLinkPath);
@@ -4008,7 +4026,9 @@ static int CreateArchiveLinkFile(const char * szFullPath1, const char * szFullPa
return GetLastError();
// Write the content of the link file
- FileStream_Write(pStream, NULL, szLinkData, (DWORD)nLength);
+ if(!FileStream_Write(pStream, NULL, szLinkData, (DWORD)nLength))
+ nError = GetLastError();
+
FileStream_Close(pStream);
return ERROR_SUCCESS;
}
@@ -4068,6 +4088,10 @@ int main(int argc, char * argv[])
if(nError == ERROR_SUCCESS)
nError = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir);
+ // Test sparse compression
+ if(nError == ERROR_SUCCESS)
+ nError = TestSparseCompression();
+
// Test reading linear file without bitmap
if(nError == ERROR_SUCCESS)
nError = TestFileStreamOperations("MPQ_2013_v4_alternate-original.MPQ", 0);
@@ -4214,11 +4238,11 @@ int main(int argc, char * argv[])
// Open an Warcraft III map locked by Spazy protector
if(nError == ERROR_SUCCESS)
nError = TestOpenArchive("MPQ_2015_v1_ProtectedMap_Spazy.w3x");
-*/
+
// Open an protected map
if(nError == ERROR_SUCCESS)
nError = TestOpenArchive("MPQ_2015_v1_flem1.w3x");
-/*-
+
// Open the multi-file archive with wrong prefix to see how StormLib deals with it
if(nError == ERROR_SUCCESS)
nError = TestOpenArchive_WillFail("flat-file://streaming/model.MPQ.0");
@@ -4311,7 +4335,10 @@ int main(int argc, char * argv[])
nError = TestOpenArchive_CraftedUserData("MPQ_2013_v4_expansion1.MPQ", "StormLibTest_CraftedMpq3_v4.mpq");
if(nError == ERROR_SUCCESS)
- nError = TestAddFile_FullTable("MPQ_2014_v1_out1.w3x", "MPQ_2014_v1_out2.w3x");
+ nError = TestAddFile_FullTable("MPQ_2014_v1_out1.w3x");
+
+ if(nError == ERROR_SUCCESS)
+ nError = TestAddFile_FullTable("MPQ_2014_v1_out2.w3x");
// Test modifying file with no (listfile) and no (attributes)
if(nError == ERROR_SUCCESS)
@@ -4399,11 +4426,11 @@ int main(int argc, char * argv[])
// Open a MPQ (add custom user data to it)
if(nError == ERROR_SUCCESS)
nError = TestCreateArchive_BigArchive("StormLibTest_BigArchive_v4.mpq");
-
+*/
// Test replacing a file with zero size file
if(nError == ERROR_SUCCESS)
nError = TestModifyArchive_ReplaceFile("MPQ_2014_v4_Base.StormReplay", "AddFile-replay.message.events");
-*/
+
#ifdef _MSC_VER
_CrtDumpMemoryLeaks();
#endif // _MSC_VER