NetPlay: Check file names when receiving GCI folder
This commit is contained in:
parent
b3a414ea9d
commit
1377f31cf8
|
@ -95,6 +95,13 @@ bool IsTitlePath(const std::string& path, std::optional<FromWhichRoot> from, u64
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool IsIllegalCharacter(char c)
|
||||
{
|
||||
static const std::unordered_set<char> illegal_chars = {'\"', '*', '/', ':', '<',
|
||||
'>', '?', '\\', '|', '\x7f'};
|
||||
return (c >= 0 && c <= 0x1F) || illegal_chars.find(c) != illegal_chars.end();
|
||||
}
|
||||
|
||||
std::string EscapeFileName(const std::string& filename)
|
||||
{
|
||||
// Prevent paths from containing special names like ., .., ..., ...., and so on
|
||||
|
@ -105,13 +112,11 @@ std::string EscapeFileName(const std::string& filename)
|
|||
std::string filename_with_escaped_double_underscores = ReplaceAll(filename, "__", "__5f____5f__");
|
||||
|
||||
// Escape all other characters that need to be escaped
|
||||
static const std::unordered_set<char> chars_to_replace = {'\"', '*', '/', ':', '<',
|
||||
'>', '?', '\\', '|', '\x7f'};
|
||||
std::string result;
|
||||
result.reserve(filename_with_escaped_double_underscores.size());
|
||||
for (char c : filename_with_escaped_double_underscores)
|
||||
{
|
||||
if ((c >= 0 && c <= 0x1F) || chars_to_replace.find(c) != chars_to_replace.end())
|
||||
if (IsIllegalCharacter(c))
|
||||
result.append(fmt::format("__{:02x}__", c));
|
||||
else
|
||||
result.push_back(c);
|
||||
|
@ -151,4 +156,11 @@ std::string UnescapeFileName(const std::string& filename)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsFileNameSafe(const std::string_view filename)
|
||||
{
|
||||
return !filename.empty() &&
|
||||
!std::all_of(filename.begin(), filename.end(), [](char c) { return c == '.'; }) &&
|
||||
std::none_of(filename.begin(), filename.end(), IsIllegalCharacter);
|
||||
}
|
||||
} // namespace Common
|
||||
|
|
|
@ -43,4 +43,6 @@ std::string EscapeFileName(const std::string& filename);
|
|||
std::string EscapePath(const std::string& path);
|
||||
// Reverses escaping done by EscapeFileName
|
||||
std::string UnescapeFileName(const std::string& filename);
|
||||
// Tests for a file name being "safe" as per the escaping defined in EscapeFileName
|
||||
bool IsFileNameSafe(const std::string_view filename);
|
||||
} // namespace Common
|
||||
|
|
|
@ -905,7 +905,8 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||
std::string file_name;
|
||||
packet >> file_name;
|
||||
|
||||
if (!DecompressPacketIntoFile(packet, path + DIR_SEP + file_name))
|
||||
if (!Common::IsFileNameSafe(file_name) ||
|
||||
!DecompressPacketIntoFile(packet, path + DIR_SEP + file_name))
|
||||
{
|
||||
SyncSaveDataResponse(false);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue