Savestates: Add TAR and VM assert

This commit is contained in:
Eladash 2023-11-25 19:52:37 +02:00 committed by Elad Ashkenazi
parent 5dbeb68ed2
commit a0b521ba8e
4 changed files with 37 additions and 7 deletions

View File

@ -2256,7 +2256,15 @@ namespace vm
void load(utils::serial& ar)
{
std::vector<std::shared_ptr<utils::shm>> shared;
shared.resize(ar.pop<usz>());
const usz shared_size = ar.pop<usz>();
if (!shared_size || ar.get_size(umax) / 4096 < shared_size)
{
fmt::throw_exception("Invalid VM serialization state: shared_size=0x%x, ar=%s", shared_size, ar);
}
shared.resize(shared_size);
for (auto& shm : shared)
{

View File

@ -1056,7 +1056,13 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
auto load_tar = [&](const std::string& path)
{
const usz size = *m_ar;
const usz size = m_ar->pop<usz>();
const usz max_data_size = m_ar->get_size(utils::add_saturate<usz>(size, m_ar->pos));
if (size % 512 || max_data_size < size || max_data_size - size < m_ar->pos)
{
fmt::throw_exception("TAR desrialization failed: Invalid size. TAR size: 0x%x, path='%s', ar: %s", size, path, *m_ar);
}
fs::remove_all(path, size == 0);
@ -1065,7 +1071,12 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
m_ar->breathe(true);
m_ar->m_max_data = m_ar->pos + size;
ensure(tar_object(*m_ar).extract(path));
m_ar->seek_pos(m_ar->m_max_data, size >= 4096);
if (m_ar->m_max_data != m_ar->pos)
{
fmt::throw_exception("TAR desrialization failed: read bytes: 0x%x, expected: 0x%x, path='%s', ar: %s", m_ar->pos - (m_ar->m_max_data - size), size, path, *m_ar);
}
m_ar->m_max_data = umax;
m_ar->breathe();
}
@ -1079,13 +1090,19 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
for (const std::string hdd0_game = rpcs3::utils::get_hdd0_dir() + "game/";;)
{
const std::string game_data = *m_ar;
const std::string game_data = m_ar->pop<std::string>();
if (game_data.empty())
{
break;
}
if (game_data.find_first_of('\0') != umax || !sysutil_check_name_string(game_data.c_str(), 1, CELL_GAME_DIRNAME_SIZE))
{
const std::basic_string_view<u8> dirname{reinterpret_cast<const u8*>(game_data.data()), game_data.size()};
fmt::throw_exception("HDD0 deserialization failed: Invalid directory name: %s, ar=%s", dirname.substr(0, CELL_GAME_DIRNAME_SIZE + 1), *m_ar);
}
load_tar(hdd0_game + game_data);
}
@ -2993,7 +3010,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
const usz tar_size = new_pos - old_pos;
if (tar_size != ar_null.pos)
if (tar_size % 512 || tar_size != ar_null.pos)
{
fmt::throw_exception("Unexpected TAR entry size (size=0x%x, expected=0x%x, entries=0x%x)", tar_size, ar_null.pos, dir_entries.size());
}

View File

@ -23,7 +23,12 @@ void fmt_class_string<utils::serial>::format(std::string& out, u64 arg)
{
const utils::serial& ar = get_object(arg);
fmt::append(out, "{ %s, 0x%x/0x%x, memory=0x%x }", ar.is_writing() ? "writing" : "reading", ar.pos, ar.data_offset + ar.data.size(), ar.data.size());
be_t<u64> sample64 = 0;
const usz read_size = std::min<usz>(ar.data.size(), sizeof(sample64));
std::memcpy(&sample64, ar.data.data() + ar.data.size() - read_size, read_size);
fmt::append(out, "{ %s, 0x%x/0x%x, memory=0x%x, sample64=0x%016x }", ar.is_writing() ? "writing" : "reading", ar.pos, ar.data_offset + ar.data.size(), ar.data.size(), sample64);
}
struct serial_ver_t

View File

@ -139,7 +139,7 @@ std::unique_ptr<utils::serial> tar_object::get_file(const std::string& path, std
}
else
{
tar_log.trace("tar_object::get_file() failed to parse header: offset=0x%x, filesize=0x%x", largest_offset, max_size);
tar_log.error("tar_object::get_file() failed to parse header: offset=0x%x, filesize=0x%x", largest_offset, max_size);
}
return { size, {} };