mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-21 18:39:57 +00:00
cellSaveData: Check filename format of savedata files (#11502)
This commit is contained in:
parent
2d5d5746d1
commit
fd6c33980b
@ -120,6 +120,91 @@ struct savedata_manager
|
||||
atomic_t<s32> last_cbresult_error_dialog{0}; // CBRESULT errors are negative
|
||||
};
|
||||
|
||||
int check_filename(std::string_view file_path, bool disallow_system_files, bool account_sfo_pfd)
|
||||
{
|
||||
if (file_path.size() >= CELL_SAVEDATA_FILENAME_SIZE)
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 71 ******
|
||||
return 71;
|
||||
}
|
||||
|
||||
auto dotpos = file_path.find_last_of('.');
|
||||
|
||||
if (dotpos == umax)
|
||||
{
|
||||
// Point to end of string instead
|
||||
dotpos = file_path.size();
|
||||
}
|
||||
|
||||
if (file_path.empty() || dotpos > 8u || file_path.size() - dotpos > 4u)
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
return 70;
|
||||
}
|
||||
|
||||
if (file_path == "."sv || (!account_sfo_pfd && (file_path == "PARAM.SFO"sv || file_path == "PARAM.PFD"sv)))
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
return 70;
|
||||
}
|
||||
|
||||
char name[CELL_SAVEDATA_FILENAME_SIZE - 3];
|
||||
|
||||
if (dotpos)
|
||||
{
|
||||
// Copy file name
|
||||
std::span dst(name, dotpos + 1);
|
||||
strcpy_trunc(dst, file_path);
|
||||
|
||||
// Allow multiple '.' even though sysutil_check_name_string does not
|
||||
std::replace(name, name + dotpos, '.', '-');
|
||||
|
||||
// Allow '_' at start even though sysutil_check_name_string does not
|
||||
if (name[0] == '_')
|
||||
{
|
||||
name[0] = '-';
|
||||
}
|
||||
|
||||
if (disallow_system_files && ((dotpos >= 5u && std::memcmp(name, "PARAM", 5) == 0) ||
|
||||
(dotpos >= 4u && std::memcmp(name, "ICON", 4) == 0) ||
|
||||
(dotpos >= 3u && std::memcmp(name, "PIC", 3) == 0) ||
|
||||
(dotpos >= 3u && std::memcmp(name, "SND", 3) == 0)))
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
return 70;
|
||||
}
|
||||
|
||||
// Check filename
|
||||
if (sysutil_check_name_string(name, 1, 9) == -1)
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
return 70;
|
||||
}
|
||||
}
|
||||
|
||||
if (file_path.size() > dotpos + 1)
|
||||
{
|
||||
// Copy file extension
|
||||
std::span dst(name, file_path.size() - dotpos);
|
||||
strcpy_trunc(dst, file_path.substr(dotpos + 1));
|
||||
|
||||
// Allow '_' at start even though sysutil_check_name_string does not
|
||||
if (name[0] == '_')
|
||||
{
|
||||
name[0] = '-';
|
||||
}
|
||||
|
||||
// Check file extension
|
||||
if (sysutil_check_name_string(name, 1, 4) == -1)
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
return 70;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::vector<SaveDataEntry> get_save_entries(const std::string& base_dir, const std::string& prefix)
|
||||
{
|
||||
std::vector<SaveDataEntry> save_entries;
|
||||
@ -159,7 +244,7 @@ static std::vector<SaveDataEntry> get_save_entries(const std::string& base_dir,
|
||||
|
||||
for (const auto& entry2 : fs::dir(base_dir + entry.name))
|
||||
{
|
||||
if (entry2.is_directory)
|
||||
if (entry2.is_directory || check_filename(vfs::unescape(entry2.name), false, true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -686,7 +771,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
|
||||
for (const auto& entry2 : fs::dir(base_dir + entry.name))
|
||||
{
|
||||
if (entry2.is_directory)
|
||||
if (entry2.is_directory || check_filename(vfs::unescape(entry2.name), false, true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1350,12 +1435,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
|
||||
if (!entry.is_directory)
|
||||
{
|
||||
if (entry.name == "."sv)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.name == "PARAM.SFO"sv || entry.name == "PARAM.PFD"sv)
|
||||
if (check_filename(entry.name, false, false))
|
||||
{
|
||||
continue; // system files are not included in the file list
|
||||
}
|
||||
@ -1575,7 +1655,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
// Read file into a vector and make a memory file
|
||||
entry.name = vfs::unescape(entry.name);
|
||||
|
||||
if (entry.name == ".")
|
||||
if (check_filename(entry.name, false, true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1647,85 +1727,12 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||
break;
|
||||
}
|
||||
|
||||
auto dotpos = file_path.find_last_of('.');
|
||||
|
||||
if (dotpos == umax)
|
||||
if (int error = check_filename(file_path, true, false))
|
||||
{
|
||||
// Point to end of string instead
|
||||
dotpos = file_path.size();
|
||||
}
|
||||
|
||||
if (file_path.empty() || dotpos > 8u || file_path.size() - dotpos > 4u)
|
||||
{
|
||||
cellSaveData.error("savedata_op(): fileSet->fileName is illegal ('%s')", file_path);
|
||||
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
savedata_result = {CELL_SAVEDATA_ERROR_PARAM, "70"};
|
||||
savedata_result = {CELL_SAVEDATA_ERROR_PARAM, "%d", error};
|
||||
break;
|
||||
}
|
||||
|
||||
char name[10];
|
||||
|
||||
if (dotpos)
|
||||
{
|
||||
// Copy file name
|
||||
std::span dst(name, dotpos + 1);
|
||||
strcpy_trunc(dst, file_path);
|
||||
|
||||
// Allow multiple '.' even though sysutil_check_name_string does not
|
||||
std::replace(name, name + dotpos, '.', '-');
|
||||
|
||||
// Allow '_' at start even though sysutil_check_name_string does not
|
||||
if (name[0] == '_')
|
||||
{
|
||||
name[0] = '-';
|
||||
}
|
||||
|
||||
if ((dotpos >= 5u && std::memcmp(name, "PARAM", 5) == 0) ||
|
||||
(dotpos >= 4u && std::memcmp(name, "ICON", 4) == 0) ||
|
||||
(dotpos >= 3u && std::memcmp(name, "PIC", 3) == 0) ||
|
||||
(dotpos >= 3u && std::memcmp(name, "SND", 3) == 0))
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
cellSaveData.error("savedata_op(): fileSet->fileName is set to a system file name (%s)", file_path);
|
||||
savedata_result = {CELL_SAVEDATA_ERROR_PARAM, "70"};
|
||||
break;
|
||||
}
|
||||
|
||||
// Check filename
|
||||
if (sysutil_check_name_string(name, 1, 9) == -1)
|
||||
{
|
||||
cellSaveData.error("savedata_op(): fileSet->fileName is illegal due to file name ('%s')", file_path);
|
||||
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
savedata_result = {CELL_SAVEDATA_ERROR_PARAM, "70"};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (file_path.size() > dotpos + 1)
|
||||
{
|
||||
// Copy file extension
|
||||
std::span dst(name, file_path.size() - dotpos);
|
||||
strcpy_trunc(dst, file_path.operator std::string_view().substr(dotpos + 1));
|
||||
|
||||
// Allow '_' at start even though sysutil_check_name_string does not
|
||||
if (name[0] == '_')
|
||||
{
|
||||
name[0] = '-';
|
||||
}
|
||||
|
||||
// Check file extension
|
||||
if (sysutil_check_name_string(name, 1, 4) == -1)
|
||||
{
|
||||
cellSaveData.error("savedata_op(): fileSet->fileName is illegal due to file extension ('%s')", file_path);
|
||||
|
||||
// ****** sysutil savedata parameter error : 70 ******
|
||||
savedata_result = {CELL_SAVEDATA_ERROR_PARAM, "70"};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == CELL_SAVEDATA_FILETYPE_SECUREFILE)
|
||||
{
|
||||
cellSaveData.notice("SECUREFILE: %s -> %s", file_path, fileSet->secureFileId);
|
||||
@ -2087,7 +2094,7 @@ static NEVER_INLINE error_code savedata_get_list_item(vm::cptr<char> dirName, vm
|
||||
|
||||
for (const auto& entry : fs::dir(save_path))
|
||||
{
|
||||
if (entry.is_directory)
|
||||
if (entry.is_directory || check_filename(vfs::unescape(entry.name), false, false))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -2095,7 +2102,8 @@ static NEVER_INLINE error_code savedata_get_list_item(vm::cptr<char> dirName, vm
|
||||
size_kbytes += ::narrow<u32>((entry.size + 1023) / 1024); // firmware rounds this value up
|
||||
}
|
||||
|
||||
*sizeKB = size_kbytes;
|
||||
// Add a seemingly constant allocation disk space of PARAM.SFO + PARAM.PFD
|
||||
*sizeKB = size_kbytes + 35;
|
||||
}
|
||||
|
||||
if (bind)
|
||||
|
Loading…
x
Reference in New Issue
Block a user