Savedata: Return errors more correctly on load.

If the buffer isn't large enough, return an error.  See #14687, thanks
sum2012 and gid15.
For many error cases, ensure SFO data and bind are not updated on failure,
and that dataSize is forced to zero on data errors.
This commit is contained in:
Unknown W. Brackets committed 2022-09-13 00:10:27 -07:00
1 parent a0515bf5ca
commit ce80900b75
2 files changed
+35 -21

No files matched your search

+3 -1
View File
@@ -1149,7 +1149,9 @@ void PSPSaveDialog::ExecuteNotVisibleIOAction() {
case SCE_UTILITY_SAVEDATA_TYPE_READDATA:
case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE:
result = param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave, param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE);
if(result == SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA)
if (result == SCE_UTILITY_SAVEDATA_ERROR_LOAD_DATA_BROKEN)
result = SCE_UTILITY_SAVEDATA_ERROR_RW_DATA_BROKEN;
if (result == SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA)
result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA;
break;
case SCE_UTILITY_SAVEDATA_TYPE_ERASE:
+32 -20
View File
@@ -589,15 +589,22 @@ int SavedataParam::Load(SceUtilitySavedataParam *param, const std::string &saveD
return isRWMode ? SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA : SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA;
}
if (fileName != "" && !pspFileSystem.GetFileInfo(filePath).exists) {
return isRWMode ? SCE_UTILITY_SAVEDATA_ERROR_RW_FILE_NOT_FOUND : SCE_UTILITY_SAVEDATA_ERROR_LOAD_FILE_NOT_FOUND;
}
// If it wasn't zero, force to zero before loading and especially in case of error.
// This isn't reset if the path doesn't even exist.
param->dataSize = 0;
int result = LoadSaveData(param, saveDirName, dirPath, secureMode);
if (result != 0)
return result;
// Load sfo
if (!LoadSFO(param, dirPath)) {
return isRWMode ? SCE_UTILITY_SAVEDATA_ERROR_RW_DATA_BROKEN : SCE_UTILITY_SAVEDATA_ERROR_LOAD_DATA_BROKEN;
}
if (fileName != "" && !pspFileSystem.GetFileInfo(filePath).exists) {
return isRWMode ? SCE_UTILITY_SAVEDATA_ERROR_RW_FILE_NOT_FOUND : SCE_UTILITY_SAVEDATA_ERROR_LOAD_FILE_NOT_FOUND;
}
// Don't know what it is, but PSP always respond this and this unlock some game
param->bind = 1021;
@@ -612,15 +619,6 @@ int SavedataParam::Load(SceUtilitySavedataParam *param, const std::string &saveD
// Load SND0.AT3
LoadFile(dirPath, SND0_FILENAME, &param->snd0FileData);
if (fileName == "") {
// Don't load savedata but return success.
return 0;
}
int result = LoadSaveData(param, saveDirName, dirPath, secureMode);
if (result != 0)
return result;
return 0;
}
@@ -638,6 +636,10 @@ int SavedataParam::LoadSaveData(SceUtilitySavedataParam *param, const std::strin
std::string filename = GetFileName(param);
std::string filePath = dirPath + "/" + filename;
// Blank filename always means success, if secureVersion was correct.
if (filename == "")
return 0;
s64 readSize;
INFO_LOG(SCEUTILITY, "Loading file with size %u in %s", param->dataBufSize, filePath.c_str());
u8 *saveData = nullptr;
@@ -667,14 +669,18 @@ int SavedataParam::LoadSaveData(SceUtilitySavedataParam *param, const std::strin
if (!saveDone) {
loadedSize = LoadNotCryptedSave(param, param->dataBuf, saveData, saveSize);
}
param->dataSize = (SceSize)saveSize;
delete[] saveData;
if (loadedSize != 0) {
// Ignore error codes.
if (loadedSize != 0 && (loadedSize & 0x80000000) == 0) {
std::string tag = "LoadSaveData/" + filePath;
NotifyMemInfo(MemBlockFlags::WRITE, param->dataBuf.ptr, loadedSize, tag.c_str(), tag.size());
}
if ((loadedSize & 0x80000000) != 0)
return loadedSize;
param->dataSize = (SceSize)saveSize;
return 0;
}
@@ -760,8 +766,12 @@ u32 SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, con
u32 sz = 0;
if (err == 0) {
if (param->dataBuf.IsValid()) {
sz = std::min((u32)saveSize, (u32)param->dataBufSize);
memcpy(data, data_base, sz);
if ((u32)saveSize > param->dataBufSize || !Memory::IsValidRange(param->dataBuf.ptr, saveSize)) {
sz = SCE_UTILITY_SAVEDATA_ERROR_LOAD_DATA_BROKEN;
} else {
sz = (u32)saveSize;
memcpy(data, data_base, sz);
}
}
saveDone = true;
}
@@ -773,9 +783,11 @@ u32 SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, con
u32 SavedataParam::LoadNotCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize) {
if (param->dataBuf.IsValid()) {
u32 sz = std::min((u32)saveSize, (u32)param->dataBufSize);
memcpy(data, saveData, sz);
return sz;
if ((u32)saveSize > param->dataBufSize || !Memory::IsValidRange(param->dataBuf.ptr, saveSize)) {
return SCE_UTILITY_SAVEDATA_ERROR_LOAD_DATA_BROKEN;
}
memcpy(data, saveData, saveSize);
return saveSize;
}
return 0;
}