fix: mario world localization crash
This commit is contained in:
@@ -71,6 +71,11 @@ static bool hasPckFolderFallback(const wstring &path, wstring &folderPath)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isValidDLCRange(const PBYTE pbData, DWORD dwLength, unsigned int offset, size_t size)
|
||||
{
|
||||
return offset <= dwLength && size <= static_cast<size_t>(dwLength) - offset;
|
||||
}
|
||||
|
||||
static DLCManager::EDLCType getFolderFileType(const wstring &path)
|
||||
{
|
||||
wstring lowerPath = toLower(path);
|
||||
@@ -568,8 +573,14 @@ bool DLCManager::readDLCDataFolder(DWORD &dwFilesProcessed, const wstring &path,
|
||||
|
||||
bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD dwLength, DLCPack *pack)
|
||||
{
|
||||
if(pbData == nullptr || pack == nullptr || dwLength < sizeof(unsigned int) * 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const PBYTE pbEnd = pbData + dwLength;
|
||||
unordered_map<int, EDLCParameterType> parameterMapping;
|
||||
unsigned int uiCurrentByte=0;
|
||||
unsigned int uiCurrentByte = 0;
|
||||
|
||||
// File format defined in the DLC_Creator
|
||||
// File format: Version 2
|
||||
@@ -582,78 +593,146 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD
|
||||
// // unsigned long, p = number of parameters
|
||||
// // p * DLC_FILE_PARAM describing each parameter for this file
|
||||
// // ulFileSize bytes of data blob of the file added
|
||||
unsigned int uiVersion=readUInt32(pbData, false);
|
||||
uiCurrentByte+=sizeof(int);
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, sizeof(unsigned int)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
unsigned int uiVersion = readUInt32(pbData, false);
|
||||
uiCurrentByte += sizeof(unsigned int);
|
||||
|
||||
bool bSwapEndian = false;
|
||||
unsigned int uiVersionSwapped = SwapInt32(uiVersion);
|
||||
if (uiVersion >= 0 && uiVersion <= CURRENT_DLC_VERSION_NUM) {
|
||||
bSwapEndian = false;
|
||||
} else if (uiVersionSwapped >= 0 && uiVersionSwapped <= CURRENT_DLC_VERSION_NUM) {
|
||||
bSwapEndian = true;
|
||||
} else {
|
||||
if(pbData!=nullptr) delete [] pbData;
|
||||
app.DebugPrintf("Unknown DLC version of %d\n", uiVersion);
|
||||
if(uiVersion <= CURRENT_DLC_VERSION_NUM)
|
||||
{
|
||||
bSwapEndian = false;
|
||||
}
|
||||
else if(uiVersionSwapped <= CURRENT_DLC_VERSION_NUM)
|
||||
{
|
||||
bSwapEndian = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("Unknown DLC version of %u\n", uiVersion);
|
||||
return false;
|
||||
}
|
||||
pack->SetDataPointer(pbData);
|
||||
unsigned int uiParameterCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian);
|
||||
uiCurrentByte+=sizeof(int);
|
||||
C4JStorage::DLC_FILE_PARAM *pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte];
|
||||
bool bXMLVersion = false;
|
||||
//DWORD dwwchCount=0;
|
||||
for(unsigned int i=0;i<uiParameterCount;i++)
|
||||
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, sizeof(unsigned int)))
|
||||
{
|
||||
pParams->dwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType;
|
||||
pParams->dwWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount;
|
||||
char16_t* wchData = reinterpret_cast<char16_t*>(pParams->wchData);
|
||||
if (bSwapEndian) {
|
||||
SwapUTF16Bytes(wchData, pParams->dwWchCount);
|
||||
return false;
|
||||
}
|
||||
unsigned int uiParameterCount = readUInt32(&pbData[uiCurrentByte], bSwapEndian);
|
||||
uiCurrentByte += sizeof(unsigned int);
|
||||
bool bXMLVersion = false;
|
||||
|
||||
for(unsigned int i = 0; i < uiParameterCount; ++i)
|
||||
{
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, sizeof(C4JStorage::DLC_FILE_PARAM)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Map DLC strings to application strings, then store the DLC index mapping to application index
|
||||
wstring parameterName(static_cast<WCHAR *>(pParams->wchData));
|
||||
C4JStorage::DLC_FILE_PARAM *pParams = reinterpret_cast<C4JStorage::DLC_FILE_PARAM *>(&pbData[uiCurrentByte]);
|
||||
unsigned int dwWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount;
|
||||
size_t paramSize = sizeof(C4JStorage::DLC_FILE_PARAM) + (dwWchCount * sizeof(WCHAR));
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, paramSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pParams->dwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType;
|
||||
pParams->dwWchCount = dwWchCount;
|
||||
char16_t* wchData = reinterpret_cast<char16_t*>(pParams->wchData);
|
||||
if (bSwapEndian)
|
||||
{
|
||||
SwapUTF16Bytes(wchData, dwWchCount);
|
||||
}
|
||||
|
||||
wstring parameterName(reinterpret_cast<WCHAR *>(pParams->wchData), pParams->dwWchCount);
|
||||
EDLCParameterType type = getParameterType(parameterName);
|
||||
if( type != e_DLCParamType_Invalid )
|
||||
if(type != e_DLCParamType_Invalid)
|
||||
{
|
||||
parameterMapping[pParams->dwType] = type;
|
||||
|
||||
if (type == e_DLCParamType_XMLVersion)
|
||||
if(type == e_DLCParamType_XMLVersion)
|
||||
{
|
||||
bXMLVersion = true;
|
||||
}
|
||||
}
|
||||
uiCurrentByte+= sizeof(C4JStorage::DLC_FILE_PARAM)+(pParams->dwWchCount*sizeof(WCHAR));
|
||||
pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte];
|
||||
|
||||
uiCurrentByte += static_cast<unsigned int>(paramSize);
|
||||
}
|
||||
//ulCurrentByte+=ulParameterCount * sizeof(C4JStorage::DLC_FILE_PARAM);
|
||||
|
||||
if (bXMLVersion)
|
||||
{
|
||||
uiCurrentByte += sizeof(int);
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, sizeof(unsigned int)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uiCurrentByte += sizeof(unsigned int);
|
||||
}
|
||||
|
||||
unsigned int uiFileCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian);
|
||||
uiCurrentByte+=sizeof(int);
|
||||
C4JStorage::DLC_FILE_DETAILS *pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte];
|
||||
|
||||
DWORD dwTemp=uiCurrentByte;
|
||||
for(unsigned int i=0;i<uiFileCount;i++)
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, sizeof(unsigned int)))
|
||||
{
|
||||
pFile->dwWchCount = bSwapEndian ? SwapInt32(pFile->dwWchCount) : pFile->dwWchCount;
|
||||
dwTemp+=sizeof(C4JStorage::DLC_FILE_DETAILS)+pFile->dwWchCount*sizeof(WCHAR);
|
||||
pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[dwTemp];
|
||||
return false;
|
||||
}
|
||||
PBYTE pbTemp=((PBYTE )pFile);//+ sizeof(C4JStorage::DLC_FILE_DETAILS)*ulFileCount;
|
||||
pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte];
|
||||
unsigned int uiFileCount = readUInt32(&pbData[uiCurrentByte], bSwapEndian);
|
||||
uiCurrentByte += sizeof(unsigned int);
|
||||
|
||||
for(unsigned int i=0;i<uiFileCount;i++)
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, sizeof(C4JStorage::DLC_FILE_DETAILS)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
C4JStorage::DLC_FILE_DETAILS *pFile = reinterpret_cast<C4JStorage::DLC_FILE_DETAILS *>(&pbData[uiCurrentByte]);
|
||||
|
||||
DWORD dwTemp = uiCurrentByte;
|
||||
for(unsigned int i = 0; i < uiFileCount; ++i)
|
||||
{
|
||||
if(!isValidDLCRange(pbData, dwLength, dwTemp, sizeof(C4JStorage::DLC_FILE_DETAILS)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pFile = reinterpret_cast<C4JStorage::DLC_FILE_DETAILS *>(&pbData[dwTemp]);
|
||||
unsigned int dwWchCount = bSwapEndian ? SwapInt32(pFile->dwWchCount) : pFile->dwWchCount;
|
||||
size_t fileDetailsSize = sizeof(C4JStorage::DLC_FILE_DETAILS) + (dwWchCount * sizeof(WCHAR));
|
||||
if(!isValidDLCRange(pbData, dwLength, dwTemp, fileDetailsSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dwTemp += static_cast<DWORD>(fileDetailsSize);
|
||||
}
|
||||
|
||||
if(!isValidDLCRange(pbData, dwLength, dwTemp, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PBYTE pbTemp = pbData + dwTemp;
|
||||
pFile = reinterpret_cast<C4JStorage::DLC_FILE_DETAILS *>(&pbData[uiCurrentByte]);
|
||||
|
||||
for(unsigned int i = 0; i < uiFileCount; ++i)
|
||||
{
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, sizeof(C4JStorage::DLC_FILE_DETAILS)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pFile = reinterpret_cast<C4JStorage::DLC_FILE_DETAILS *>(&pbData[uiCurrentByte]);
|
||||
unsigned int dwWchCount = bSwapEndian ? SwapInt32(pFile->dwWchCount) : pFile->dwWchCount;
|
||||
unsigned int uiFileSize = bSwapEndian ? SwapInt32(pFile->uiFileSize) : pFile->uiFileSize;
|
||||
size_t fileHeaderSize = sizeof(C4JStorage::DLC_FILE_DETAILS) + (dwWchCount * sizeof(WCHAR));
|
||||
if(!isValidDLCRange(pbData, dwLength, uiCurrentByte, fileHeaderSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pFile->dwType = bSwapEndian ? SwapInt32(pFile->dwType) : pFile->dwType;
|
||||
pFile->uiFileSize = bSwapEndian ? SwapInt32(pFile->uiFileSize) : pFile->uiFileSize;
|
||||
pFile->uiFileSize = uiFileSize;
|
||||
char16_t* wchFile = reinterpret_cast<char16_t*>(pFile->wchFile);
|
||||
if (bSwapEndian) {
|
||||
SwapUTF16Bytes(wchFile, pFile->dwWchCount);
|
||||
if (bSwapEndian)
|
||||
{
|
||||
SwapUTF16Bytes(wchFile, dwWchCount);
|
||||
}
|
||||
|
||||
EDLCType type = static_cast<EDLCType>(pFile->dwType);
|
||||
@@ -670,43 +749,65 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD
|
||||
dlcFile = pack->addFile(type,(WCHAR *)pFile->wchFile);
|
||||
}
|
||||
|
||||
// Params
|
||||
uiParameterCount=readUInt32(pbTemp, bSwapEndian);
|
||||
pbTemp+=sizeof(int);
|
||||
pParams = (C4JStorage::DLC_FILE_PARAM *)pbTemp;
|
||||
for(unsigned int j=0;j<uiParameterCount;j++)
|
||||
if(!isValidDLCRange(pbData, dwLength, static_cast<unsigned int>(pbTemp - pbData), sizeof(unsigned int)))
|
||||
{
|
||||
//DLCManager::EDLCParameterType paramType = DLCManager::e_DLCParamType_Invalid;
|
||||
return false;
|
||||
}
|
||||
uiParameterCount = readUInt32(pbTemp, bSwapEndian);
|
||||
pbTemp += sizeof(unsigned int);
|
||||
C4JStorage::DLC_FILE_PARAM *pParams = reinterpret_cast<C4JStorage::DLC_FILE_PARAM *>(pbTemp);
|
||||
for(unsigned int j = 0; j < uiParameterCount; ++j)
|
||||
{
|
||||
if(!isValidDLCRange(pbData, dwLength, static_cast<unsigned int>(pbTemp - pbData), sizeof(C4JStorage::DLC_FILE_PARAM)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pParams = reinterpret_cast<C4JStorage::DLC_FILE_PARAM *>(pbTemp);
|
||||
unsigned int dwParamWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount;
|
||||
size_t paramSize = sizeof(C4JStorage::DLC_FILE_PARAM) + (dwParamWchCount * sizeof(WCHAR));
|
||||
if(!isValidDLCRange(pbData, dwLength, static_cast<unsigned int>(pbTemp - pbData), paramSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pParams->dwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType;
|
||||
pParams->dwWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount;
|
||||
pParams->dwWchCount = dwParamWchCount;
|
||||
char16_t* wchData = reinterpret_cast<char16_t*>(pParams->wchData);
|
||||
if (bSwapEndian) {
|
||||
SwapUTF16Bytes(wchData, pParams->dwWchCount);
|
||||
if (bSwapEndian)
|
||||
{
|
||||
SwapUTF16Bytes(wchData, dwParamWchCount);
|
||||
}
|
||||
|
||||
auto it = parameterMapping.find(pParams->dwType);
|
||||
|
||||
if(it != parameterMapping.end() )
|
||||
if(it != parameterMapping.end())
|
||||
{
|
||||
if(type == e_DLCType_PackConfig)
|
||||
{
|
||||
pack->addParameter(it->second,(WCHAR *)pParams->wchData);
|
||||
}
|
||||
else
|
||||
else if(dlcFile != nullptr)
|
||||
{
|
||||
if(dlcFile != nullptr) dlcFile->addParameter(it->second,(WCHAR *)pParams->wchData);
|
||||
else if(dlcTexturePack != nullptr) dlcTexturePack->addParameter(it->second, (WCHAR *)pParams->wchData);
|
||||
dlcFile->addParameter(it->second,(WCHAR *)pParams->wchData);
|
||||
}
|
||||
else if(dlcTexturePack != nullptr)
|
||||
{
|
||||
dlcTexturePack->addParameter(it->second, (WCHAR *)pParams->wchData);
|
||||
}
|
||||
}
|
||||
pbTemp+=sizeof(C4JStorage::DLC_FILE_PARAM)+(sizeof(WCHAR)*pParams->dwWchCount);
|
||||
pParams = (C4JStorage::DLC_FILE_PARAM *)pbTemp;
|
||||
|
||||
pbTemp += static_cast<unsigned int>(paramSize);
|
||||
}
|
||||
|
||||
if(!isValidDLCRange(pbData, dwLength, static_cast<unsigned int>(pbTemp - pbData), uiFileSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//pbTemp+=ulParameterCount * sizeof(C4JStorage::DLC_FILE_PARAM);
|
||||
|
||||
if(dlcTexturePack != nullptr)
|
||||
{
|
||||
DWORD texturePackFilesProcessed = 0;
|
||||
bool validPack = processDLCDataFile(texturePackFilesProcessed,pbTemp,pFile->uiFileSize,dlcTexturePack);
|
||||
bool validPack = processDLCDataFile(texturePackFilesProcessed, pbTemp, uiFileSize, dlcTexturePack);
|
||||
pack->SetDataPointer(nullptr); // If it's a child pack, it doesn't own the data
|
||||
if(!validPack || texturePackFilesProcessed == 0)
|
||||
{
|
||||
@@ -726,8 +827,7 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD
|
||||
}
|
||||
else if(dlcFile != nullptr)
|
||||
{
|
||||
// Data
|
||||
dlcFile->addData(pbTemp,pFile->uiFileSize);
|
||||
dlcFile->addData(pbTemp, uiFileSize);
|
||||
|
||||
// TODO - 4J Stu Remove the need for this vSkinNames vector, or manage it differently
|
||||
switch(pFile->dwType)
|
||||
@@ -740,14 +840,11 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD
|
||||
++dwFilesProcessed;
|
||||
}
|
||||
|
||||
// Move the pointer to the start of the next files data;
|
||||
pbTemp+=pFile->uiFileSize;
|
||||
uiCurrentByte+=sizeof(C4JStorage::DLC_FILE_DETAILS)+pFile->dwWchCount*sizeof(WCHAR);
|
||||
|
||||
pFile=(C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte];
|
||||
pbTemp += uiFileSize;
|
||||
uiCurrentByte += static_cast<unsigned int>(fileHeaderSize);
|
||||
}
|
||||
|
||||
if( pack->getDLCItemsCount(e_DLCType_GameRules) > 0
|
||||
if(pack->getDLCItemsCount(e_DLCType_GameRules) > 0
|
||||
|| pack->getDLCItemsCount(e_DLCType_GameRulesHeader) > 0)
|
||||
{
|
||||
app.m_gameRules.loadGameRules(pack);
|
||||
|
||||
Reference in New Issue
Block a user