diff --git a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp index 539acdf1f4..4b9f1e8ac3 100644 --- a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp @@ -11,6 +11,7 @@ #include "Loader/PSF.h" #include "Utilities/StrUtil.h" +#include "Utilities/span.h" #include #include @@ -1400,64 +1401,75 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v break; } - const auto fileName = fileSet->fileName.get_ptr(); + const char* fileName = fileSet->fileName.get_ptr(); - const auto termpos = std::find(fileName, fileName + CELL_SAVEDATA_FILENAME_SIZE, '\0'); - - if (termpos == fileName + CELL_SAVEDATA_FILENAME_SIZE) + if (const auto termpos = std::memchr(fileName, '\0', CELL_SAVEDATA_FILENAME_SIZE)) + { + file_path.assign(fileName, static_cast(termpos)); + } + else { // ****** sysutil savedata parameter error : 71 ****** savedata_result = {CELL_SAVEDATA_ERROR_PARAM, "71"}; break; } - char name[10]; - name[0] = '.'; + auto dotpos = file_path.find_last_of('.'); - const auto dotpos = std::find_end(fileName, termpos, name, name + 1); - - if (dotpos > fileName + 8 || termpos - dotpos > 4) + if (dotpos == umax) { + // 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"}; break; } - if (dotpos != fileName) + char name[10]; + + if (dotpos) { - // Reset for filename - std::memset(name, 0, 10); - std::copy(fileName, dotpos, name); + // Copy file name + gsl::span dst(name, dotpos + 1); + strcpy_trunc(dst, file_path); // Allow multiple '.' even though sysutil_check_name_string does not - std::replace(name, name + 9, '.', '-'); + std::replace(name, name + dotpos, '.', '-'); // 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 (dotpos < termpos - 1) + if (file_path.size() > dotpos + 1) { - // Reset for file extension - std::memset(name, 0, 5); - std::copy(dotpos + 1, termpos, name); + // Copy file extension + gsl::span dst(name, file_path.size() - dotpos); + strcpy_trunc(dst, file_path.operator std::string_view().substr(dotpos + 1)); // 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; } } - file_path = fileName; - if (type == CELL_SAVEDATA_FILETYPE_SECUREFILE) { cellSaveData.notice("SECUREFILE: %s -> %s", file_path, fileSet->secureFileId); @@ -1501,8 +1513,6 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v psf.emplace("*" + file_path, fileSet->fileType == CELL_SAVEDATA_FILETYPE_SECUREFILE); - const u32 access_size = std::min(fileSet->fileSize, fileSet->fileBufSize); - // clang-format off auto add_to_blist = [&](const std::string& to_add) { @@ -1558,7 +1568,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v // Read from memory file to vm const u64 sr = file.seek(fileSet->fileOffset); - const u64 rr = lv2_file::op_read(file, fileSet->fileBuf, access_size); + const u64 rr = lv2_file::op_read(file, fileSet->fileBuf, fileSet->fileSize); fileGet->excSize = ::narrow(rr); break; } @@ -1593,7 +1603,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v // Write to memory file and truncate const u64 sr = file.seek(fileSet->fileOffset); - const u64 wr = lv2_file::op_write(file, fileSet->fileBuf, access_size); + const u64 wr = lv2_file::op_write(file, fileSet->fileBuf, fileSet->fileSize); file.trunc(sr + wr); fileGet->excSize = ::narrow(wr); all_times.erase(file_path); @@ -1644,7 +1654,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v // Write to memory file normally const u64 sr = file.seek(fileSet->fileOffset); - const u64 wr = lv2_file::op_write(file, fileSet->fileBuf, access_size); + const u64 wr = lv2_file::op_write(file, fileSet->fileBuf, fileSet->fileSize); fileGet->excSize = ::narrow(wr); all_times.erase(file_path); add_to_blist(file_path);