Safety checks in all SFO readings

This commit is contained in:
Vinicius Rangel 2024-09-21 15:08:08 -03:00
commit 6c73d80641
No known key found for this signature in database
GPG key ID: A5B154D904B761D9
8 changed files with 121 additions and 54 deletions

View file

@ -4,6 +4,7 @@
#include <cmath> #include <cmath>
#include "app_content.h" #include "app_content.h"
#include "common/assert.h"
#include "common/io_file.h" #include "common/io_file.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/path_util.h" #include "common/path_util.h"
@ -246,7 +247,11 @@ int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initPar
auto* param_sfo = Common::Singleton<PSF>::Instance(); auto* param_sfo = Common::Singleton<PSF>::Instance();
const auto addons_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir); const auto addons_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir);
title_id = *param_sfo->GetString("TITLE_ID"); if (const auto value = param_sfo->GetString("TITLE_ID"); value.has_value()) {
title_id = *value;
} else {
UNREACHABLE_MSG("Failed to get TITLE_ID");
}
auto addon_path = addons_dir / title_id; auto addon_path = addons_dir / title_id;
if (std::filesystem::exists(addon_path)) { if (std::filesystem::exists(addon_path)) {
for (const auto& entry : std::filesystem::directory_iterator(addon_path)) { for (const auto& entry : std::filesystem::directory_iterator(addon_path)) {

View file

@ -63,8 +63,9 @@ SaveDialogState::SaveDialogState(const OrbisSaveDataDialogParam& param) {
this->enable_back = {param.optionParam->back == OptionBack::ENABLE}; this->enable_back = {param.optionParam->back == OptionBack::ENABLE};
} }
static std::string game_serial{*Common::Singleton<PSF>::Instance()->GetString("CONTENT_ID"), 7, const auto content_id = Common::Singleton<PSF>::Instance()->GetString("CONTENT_ID");
9}; ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID");
static std::string game_serial{*content_id, 7, 9};
const auto item = param.items; const auto item = param.items;
this->user_id = item->userId; this->user_id = item->userId;
@ -115,9 +116,9 @@ SaveDialogState::SaveDialogState(const OrbisSaveDataDialogParam& param) {
.dir_name = std::string{dir_name}, .dir_name = std::string{dir_name},
.icon = icon, .icon = icon,
.title = std::string{*param_sfo.GetString(SaveParams::MAINTITLE)}, .title = std::string{param_sfo.GetString(SaveParams::MAINTITLE).value_or("Unknown")},
.subtitle = std::string{*param_sfo.GetString(SaveParams::SUBTITLE)}, .subtitle = std::string{param_sfo.GetString(SaveParams::SUBTITLE).value_or("")},
.details = std::string{*param_sfo.GetString(SaveParams::DETAIL)}, .details = std::string{param_sfo.GetString(SaveParams::DETAIL).value_or("")},
.date = date_str, .date = date_str,
.size = size_str, .size = size_str,
.last_write = param_sfo.GetLastWrite(), .last_write = param_sfo.GetLastWrite(),

View file

@ -308,7 +308,9 @@ static std::array<std::optional<SaveInstance>, 16> g_mount_slots;
static void initialize() { static void initialize() {
g_initialized = true; g_initialized = true;
static auto* param_sfo = Common::Singleton<PSF>::Instance(); static auto* param_sfo = Common::Singleton<PSF>::Instance();
g_game_serial = std::string(*param_sfo->GetString("CONTENT_ID"), 7, 9); const auto content_id = param_sfo->GetString("CONTENT_ID");
ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID");
g_game_serial = std::string(*content_id, 7, 9);
} }
// game_00other | game*other // game_00other | game*other
@ -479,9 +481,9 @@ static Error Umount(const OrbisSaveDataMountPoint* mountPoint, bool call_backup
void OrbisSaveDataParam::FromSFO(const PSF& sfo) { void OrbisSaveDataParam::FromSFO(const PSF& sfo) {
memset(this, 0, sizeof(OrbisSaveDataParam)); memset(this, 0, sizeof(OrbisSaveDataParam));
title.FromString(*sfo.GetString(SaveParams::MAINTITLE)); title.FromString(sfo.GetString(SaveParams::MAINTITLE).value_or("Unknown"));
subTitle.FromString(*sfo.GetString(SaveParams::SUBTITLE)); subTitle.FromString(sfo.GetString(SaveParams::SUBTITLE).value_or(""));
detail.FromString(*sfo.GetString(SaveParams::DETAIL)); detail.FromString(sfo.GetString(SaveParams::DETAIL).value_or(""));
userParam = sfo.GetInteger(SaveParams::SAVEDATA_LIST_PARAM).value_or(0); userParam = sfo.GetInteger(SaveParams::SAVEDATA_LIST_PARAM).value_or(0);
const auto time_since_epoch = sfo.GetLastWrite().time_since_epoch(); const auto time_since_epoch = sfo.GetLastWrite().time_since_epoch();
mtime = chrono::duration_cast<chrono::seconds>(time_since_epoch).count(); mtime = chrono::duration_cast<chrono::seconds>(time_since_epoch).count();
@ -1019,7 +1021,7 @@ Error PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
const size_t s = param_sfo->GetString(key)->copy(param, paramBufSize - 1); const size_t s = param_sfo->GetString(key).value_or("").copy(param, paramBufSize - 1);
param[s] = '\0'; // null terminate param[s] = '\0'; // null terminate
if (gotSize != nullptr) { if (gotSize != nullptr) {
*gotSize = s + 1; *gotSize = s + 1;

View file

@ -102,7 +102,9 @@ void Emulator::Run(const std::filesystem::path& file) {
auto* param_sfo = Common::Singleton<PSF>::Instance(); auto* param_sfo = Common::Singleton<PSF>::Instance();
const bool success = param_sfo->Open(sce_sys_folder / "param.sfo"); const bool success = param_sfo->Open(sce_sys_folder / "param.sfo");
ASSERT_MSG(success, "Failed to open param.sfo"); ASSERT_MSG(success, "Failed to open param.sfo");
id = std::string(*param_sfo->GetString("CONTENT_ID"), 7, 9); const auto content_id = param_sfo->GetString("CONTENT_ID");
ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID");
id = std::string(*content_id, 7, 9);
Libraries::NpTrophy::game_serial = id; Libraries::NpTrophy::game_serial = id;
const auto trophyDir = const auto trophyDir =
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles"; Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles";
@ -115,10 +117,10 @@ void Emulator::Run(const std::filesystem::path& file) {
#ifdef ENABLE_QT_GUI #ifdef ENABLE_QT_GUI
MemoryPatcher::g_game_serial = id; MemoryPatcher::g_game_serial = id;
#endif #endif
title = *param_sfo->GetString("TITLE"); title = param_sfo->GetString("TITLE").value_or("Unknown title");
LOG_INFO(Loader, "Game id: {} Title: {}", id, title); LOG_INFO(Loader, "Game id: {} Title: {}", id, title);
u32 fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000); u32 fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000);
app_version = *param_sfo->GetString("APP_VER"); app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version);
} else if (entry.path().filename() == "playgo-chunk.dat") { } else if (entry.path().filename() == "playgo-chunk.dat") {
auto* playgo = Common::Singleton<PlaygoFile>::Instance(); auto* playgo = Common::Singleton<PlaygoFile>::Instance();

View file

@ -32,16 +32,31 @@ public:
QString iconpath = QString::fromStdString(game.icon_path); QString iconpath = QString::fromStdString(game.icon_path);
game.icon = QImage(iconpath); game.icon = QImage(iconpath);
game.pic_path = game.path + "/sce_sys/pic1.png"; game.pic_path = game.path + "/sce_sys/pic1.png";
game.name = *psf.GetString("TITLE"); if (const auto title = psf.GetString("TITLE"); title.has_value()) {
game.serial = *psf.GetString("TITLE_ID"); game.name = *title;
game.region = }
GameListUtils::GetRegion(psf.GetString("CONTENT_ID")->at(0)).toStdString(); if (const auto title_id = psf.GetString("TITLE_ID"); title_id.has_value()) {
u32 fw_int = *psf.GetInteger("SYSTEM_VER"); game.serial = *title_id;
QString fw = QString::number(fw_int, 16); }
QString fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.') if (const auto content_id = psf.GetString("CONTENT_ID");
: fw.left(3).insert(1, '.'); content_id.has_value() && !content_id->empty()) {
game.fw = (fw_int == 0) ? "0.00" : fw_.toStdString(); game.region = GameListUtils::GetRegion(content_id->at(0)).toStdString();
game.version = *psf.GetString("APP_VER"); }
if (const auto fw_int_opt = psf.GetInteger("SYSTEM_VER"); fw_int_opt.has_value()) {
auto fw_int = *fw_int_opt;
if (fw_int == 0) {
game.fw = "0.00";
} else {
QString fw = QString::number(fw_int, 16);
QString fw_ = fw.length() > 7
? QString::number(fw_int, 16).left(3).insert(2, '.')
: fw.left(3).insert(1, '.');
game.fw = fw_.toStdString();
}
}
if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) {
game.version = *app_ver;
}
} }
return game; return game;
} }

View file

@ -96,25 +96,37 @@ public:
QTableWidgetItem* valueItem; QTableWidgetItem* valueItem;
switch (entry.param_fmt) { switch (entry.param_fmt) {
case PSFEntryFmt::Binary: { case PSFEntryFmt::Binary: {
const auto bin = psf.GetBinary(entry.key);
const auto bin = *psf.GetBinary(entry.key); if (!bin.has_value()) {
std::string text; valueItem = new QTableWidgetItem(QString("Unknown"));
text.reserve(bin.size() * 2); } else {
for (const auto& c : bin) { std::string text;
static constexpr char hex[] = "0123456789ABCDEF"; text.reserve(bin->size() * 2);
text.push_back(hex[c >> 4 & 0xF]); for (const auto& c : *bin) {
text.push_back(hex[c & 0xF]); static constexpr char hex[] = "0123456789ABCDEF";
text.push_back(hex[c >> 4 & 0xF]);
text.push_back(hex[c & 0xF]);
}
valueItem = new QTableWidgetItem(QString::fromStdString(text));
} }
valueItem = new QTableWidgetItem(QString::fromStdString(text));
} break; } break;
case PSFEntryFmt::Text: { case PSFEntryFmt::Text: {
auto text = *psf.GetString(entry.key); auto text = psf.GetString(entry.key);
valueItem = new QTableWidgetItem(QString::fromStdString(std::string{text})); if (!text.has_value()) {
valueItem = new QTableWidgetItem(QString("Unknown"));
} else {
valueItem =
new QTableWidgetItem(QString::fromStdString(std::string{*text}));
}
} break; } break;
case PSFEntryFmt::Integer: { case PSFEntryFmt::Integer: {
auto integer = *psf.GetInteger(entry.key); auto integer = psf.GetInteger(entry.key);
valueItem = if (!integer.has_value()) {
new QTableWidgetItem(QString("0x") + QString::number(integer, 16)); valueItem = new QTableWidgetItem(QString("Unknown"));
} else {
valueItem =
new QTableWidgetItem(QString("0x") + QString::number(*integer, 16));
}
} break; } break;
} }

View file

@ -636,9 +636,19 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setWindowTitle(tr("PKG Extraction")); msgBox.setWindowTitle(tr("PKG Extraction"));
psf.Open(pkg.sfo); if (!psf.Open(pkg.sfo)) {
QMessageBox::critical(this, tr("PKG ERROR"),
"Could not read SFO. Check log for details");
return;
}
std::string content_id{*psf.GetString("CONTENT_ID")}; std::string content_id;
if (auto value = psf.GetString("CONTENT_ID"); value.has_value()) {
content_id = std::string{*value};
} else {
QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no CONTENT_ID");
return;
}
std::string entitlement_label = Common::SplitString(content_id, '-')[2]; std::string entitlement_label = Common::SplitString(content_id, '-')[2];
auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) /
@ -647,11 +657,21 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
auto category = psf.GetString("CATEGORY"); auto category = psf.GetString("CATEGORY");
if (pkgType.contains("PATCH")) { if (pkgType.contains("PATCH")) {
QString pkg_app_version = QString pkg_app_version;
QString::fromStdString(std::string{*psf.GetString("APP_VER")}); if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) {
pkg_app_version = QString::fromStdString(std::string{*app_ver});
} else {
QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no APP_VER");
return;
}
psf.Open(extract_path / "sce_sys" / "param.sfo"); psf.Open(extract_path / "sce_sys" / "param.sfo");
QString game_app_version = QString game_app_version;
QString::fromStdString(std::string{*psf.GetString("APP_VER")}); if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) {
game_app_version = QString::fromStdString(std::string{*app_ver});
} else {
QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no APP_VER");
return;
}
double appD = game_app_version.toDouble(); double appD = game_app_version.toDouble();
double pkgD = pkg_app_version.toDouble(); double pkgD = pkg_app_version.toDouble();
if (pkgD == appD) { if (pkgD == appD) {

View file

@ -110,12 +110,16 @@ void PKGViewer::ProcessPKGInfo() {
#endif #endif
package.Open(path); package.Open(path);
psf.Open(package.sfo); psf.Open(package.sfo);
QString title_name = QString::fromStdString(std::string{*psf.GetString("TITLE")}); QString title_name =
QString title_id = QString::fromStdString(std::string{*psf.GetString("TITLE_ID")}); QString::fromStdString(std::string{psf.GetString("TITLE").value_or("Unknown")});
QString app_type = game_list_util.GetAppType(*psf.GetInteger("APP_TYPE")); QString title_id =
QString app_version = QString::fromStdString(std::string{*psf.GetString("APP_VER")}); QString::fromStdString(std::string{psf.GetString("TITLE_ID").value_or("Unknown")});
QString title_category = QString::fromStdString(std::string{*psf.GetString("CATEGORY")}); QString app_type = GameListUtils::GetAppType(psf.GetInteger("APP_TYPE").value_or(0));
QString pkg_size = game_list_util.FormatSize(package.GetPkgHeader().pkg_size); QString app_version =
QString::fromStdString(std::string{psf.GetString("APP_VER").value_or("Unknown")});
QString title_category =
QString::fromStdString(std::string{psf.GetString("CATEGORY").value_or("Unknown")});
QString pkg_size = GameListUtils::FormatSize(package.GetPkgHeader().pkg_size);
pkg_content_flag = package.GetPkgHeader().pkg_content_flags; pkg_content_flag = package.GetPkgHeader().pkg_content_flags;
QString flagss = ""; QString flagss = "";
for (const auto& flag : package.flagNames) { for (const auto& flag : package.flagNames) {
@ -126,11 +130,17 @@ void PKGViewer::ProcessPKGInfo() {
} }
} }
u32 fw_int = *psf.GetInteger("SYSTEM_VER"); QString fw_ = "Unknown";
QString fw = QString::number(fw_int, 16); if (const auto fw_int_opt = psf.GetInteger("SYSTEM_VER"); fw_int_opt.has_value()) {
QString fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.') const u32 fw_int = *fw_int_opt;
if (fw_int == 0) {
fw_ = "0.00";
} else {
QString fw = QString::number(fw_int, 16);
fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.')
: fw.left(3).insert(1, '.'); : fw.left(3).insert(1, '.');
fw_ = (fw_int == 0) ? "0.00" : fw_; }
}
char region = package.GetPkgHeader().pkg_content_id[0]; char region = package.GetPkgHeader().pkg_content_id[0];
QString pkg_info = ""; QString pkg_info = "";
if (title_category == "gd" && !flagss.contains("PATCH")) { if (title_category == "gd" && !flagss.contains("PATCH")) {