Skip to content

Commit 07d0cf7

Browse files
committed
Ensure file path is within bounds
An old upstream change [ci skip]
1 parent 222637b commit 07d0cf7

File tree

2 files changed

+87
-52
lines changed

2 files changed

+87
-52
lines changed

Client/mods/deathmatch/logic/CPacketHandler.cpp

Lines changed: 86 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4999,6 +4999,8 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
49994999
return;
50005000
}
50015001

5002+
bool bFatalError = false;
5003+
50025004
CResource* pResource = g_pClientGame->m_pResourceManager->Add(usResourceID, szResourceName, pResourceEntity, pResourceDynamicEntity, strMinServerReq,
50035005
strMinClientReq, bEnableOOP);
50045006
if (pResource)
@@ -5047,61 +5049,80 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
50475049
}
50485050
szChunkData[ucChunkSize] = NULL;
50495051

5050-
bitStream.Read(ucChunkSubType);
5051-
bitStream.Read(chunkChecksum.ulCRC);
5052-
bitStream.Read((char*)chunkChecksum.md5.data, sizeof(chunkChecksum.md5.data));
5053-
bitStream.Read(dChunkDataSize);
5054-
5055-
uint uiDownloadSize = (uint)dChunkDataSize;
5056-
uiTotalSizeProcessed += uiDownloadSize;
5057-
if (uiTotalSizeProcessed / 1024 / 1024 > 50)
5058-
g_pCore->UpdateDummyProgress(uiTotalSizeProcessed / 1024 / 1024, " MB");
5059-
5060-
// Create the resource downloadable
5061-
CDownloadableResource* pDownloadableResource = NULL;
5062-
switch (ucChunkSubType)
5052+
std::string strChunkData = szChunkData;
5053+
// make the full file path (c:/path/to/mods/deathmatch/resources/resource/)
5054+
std::string strMetaPathTemp;
5055+
std::string strResPathTemp = pResource->GetResourceDirectoryPath(ACCESS_PUBLIC, strMetaPathTemp);
5056+
std::filesystem::path fsResPath = std::filesystem::path(strResPathTemp).lexically_normal();
5057+
std::string strResPath = fsResPath.string();
5058+
// make the full file path (c:/path/to/mods/deathmatch/resources/resource/file.lua)
5059+
std::string strResFilePathTemp = strResPath + static_cast<char>(std::filesystem::path::preferred_separator) + strChunkData;
5060+
std::filesystem::path fsResFilePath = std::filesystem::path(strResFilePathTemp).lexically_normal();
5061+
std::string strResFilePath = fsResFilePath.string();
5062+
// check that full file path contains full resource path
5063+
if (strResFilePath.rfind(strResPath.c_str(), 0) != 0)
5064+
{
5065+
bFatalError = true;
5066+
AddReportLog(2081, SString("Path %s (expected %s)", strResFilePath.c_str(), strResPath.c_str()));
5067+
}
5068+
else
50635069
{
5064-
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE:
5070+
bitStream.Read(ucChunkSubType);
5071+
bitStream.Read(chunkChecksum.ulCRC);
5072+
bitStream.Read((char*)chunkChecksum.md5.data, sizeof(chunkChecksum.md5.data));
5073+
bitStream.Read(dChunkDataSize);
5074+
5075+
uint uiDownloadSize = (uint)dChunkDataSize;
5076+
uiTotalSizeProcessed += uiDownloadSize;
5077+
if (uiTotalSizeProcessed / 1024 / 1024 > 50)
5078+
g_pCore->UpdateDummyProgress(uiTotalSizeProcessed / 1024 / 1024, " MB");
5079+
5080+
// Create the resource downloadable
5081+
CDownloadableResource* pDownloadableResource = NULL;
5082+
switch (ucChunkSubType)
50655083
{
5066-
bool bDownload = bitStream.ReadBit();
5067-
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE, szChunkData,
5068-
uiDownloadSize, chunkChecksum, bDownload);
5069-
5070-
break;
5071-
}
5072-
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT:
5073-
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT, szChunkData,
5074-
uiDownloadSize, chunkChecksum, true);
5084+
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE:
5085+
{
5086+
bool bDownload = bitStream.ReadBit();
5087+
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE, szChunkData,
5088+
uiDownloadSize, chunkChecksum, bDownload);
50755089

5076-
break;
5077-
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_CONFIG:
5078-
pDownloadableResource = pResource->AddConfigFile(szChunkData, uiDownloadSize, chunkChecksum);
5090+
break;
5091+
}
5092+
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT:
5093+
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT, szChunkData,
5094+
uiDownloadSize, chunkChecksum, true);
50795095

5080-
break;
5081-
default:
5096+
break;
5097+
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_CONFIG:
5098+
pDownloadableResource = pResource->AddConfigFile(szChunkData, uiDownloadSize, chunkChecksum);
50825099

5083-
break;
5084-
}
5100+
break;
5101+
default:
50855102

5086-
// Does the Client and Server checksum differ?
5087-
if (pDownloadableResource && !pDownloadableResource->DoesClientAndServerChecksumMatch())
5088-
{
5089-
// Delete the file that already exists
5090-
FileDelete(pDownloadableResource->GetName());
5091-
if (FileExists(pDownloadableResource->GetName()))
5092-
{
5093-
SString strMessage("Unable to delete old file %s", *ConformResourcePath(pDownloadableResource->GetName()));
5094-
g_pClientGame->TellServerSomethingImportant(1009, strMessage);
5103+
break;
50955104
}
50965105

5097-
// Is it downloadable now?
5098-
if (pDownloadableResource->IsAutoDownload())
5106+
// Does the Client and Server checksum differ?
5107+
if (pDownloadableResource && !pDownloadableResource->DoesClientAndServerChecksumMatch())
50995108
{
5100-
// Make sure the directory exists
5101-
MakeSureDirExists(pDownloadableResource->GetName());
5109+
// Delete the file that already exists
5110+
FileDelete(pDownloadableResource->GetName());
5111+
if (FileExists(pDownloadableResource->GetName()))
5112+
{
5113+
SString strMessage("Unable to delete old file %s", *ConformResourcePath(pDownloadableResource->GetName()));
5114+
g_pClientGame->TellServerSomethingImportant(1009, strMessage);
5115+
}
51025116

5103-
// Queue the file to be downloaded
5104-
g_pClientGame->GetResourceFileDownloadManager()->AddPendingFileDownload(pDownloadableResource);
5117+
// Is it downloadable now?
5118+
if (pDownloadableResource->IsAutoDownload())
5119+
{
5120+
// Make sure the directory exists
5121+
MakeSureDirExists(pDownloadableResource->GetName());
5122+
5123+
// Queue the file to be downloaded
5124+
g_pClientGame->GetResourceFileDownloadManager()->AddPendingFileDownload(pDownloadableResource);
5125+
}
51055126
}
51065127
}
51075128
}
@@ -5116,17 +5137,25 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
51165137
delete[] szChunkData;
51175138
szChunkData = NULL;
51185139
}
5119-
}
51205140

5121-
g_pClientGame->GetResourceFileDownloadManager()->UpdatePendingDownloads();
5141+
if (bFatalError)
5142+
{
5143+
break;
5144+
}
5145+
}
51225146

5123-
// Are there any resources to being downloaded?
5124-
if (!g_pClientGame->GetResourceFileDownloadManager()->IsTransferringInitialFiles())
5147+
if (!bFatalError)
51255148
{
5126-
// Load the resource now
5127-
if (pResource->CanBeLoaded())
5149+
g_pClientGame->GetResourceFileDownloadManager()->UpdatePendingDownloads();
5150+
5151+
// Are there any resources to being downloaded?
5152+
if (!g_pClientGame->GetResourceFileDownloadManager()->IsTransferringInitialFiles())
51285153
{
5129-
pResource->Load();
5154+
// Load the resource now
5155+
if (pResource->CanBeLoaded())
5156+
{
5157+
pResource->Load();
5158+
}
51305159
}
51315160
}
51325161
}
@@ -5136,6 +5165,11 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
51365165

51375166
g_pCore->UpdateDummyProgress(0);
51385167
totalSizeProcessedResetTimer.Reset();
5168+
5169+
if (bFatalError)
5170+
{
5171+
RaiseFatalError(2081);
5172+
}
51395173
}
51405174

51415175
void CPacketHandler::Packet_ResourceStop(NetBitStreamInterface& bitStream)

Client/mods/deathmatch/logic/CPacketHandler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#pragma once
1313

14+
#include <filesystem>
1415
#include <CClientCommon.h>
1516

1617
class CClientEntity;

0 commit comments

Comments
 (0)