mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
Improve ELF/Trophy loader's error checking
This commit is contained in:
parent
a67b347966
commit
2f333424a6
6 changed files with 61 additions and 53 deletions
|
@ -1556,6 +1556,17 @@ bool fs::dir::open(const std::string& path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fs::file::strict_read_check(u64 _size, u64 type_size) const
|
||||||
|
{
|
||||||
|
if (usz pos0 = pos(), size0 = size(); pos0 >= size0 || (size0 - pos0) / type_size < _size)
|
||||||
|
{
|
||||||
|
fs::g_tls_error = fs::error::inval;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& fs::get_config_dir()
|
const std::string& fs::get_config_dir()
|
||||||
{
|
{
|
||||||
// Use magic static
|
// Use magic static
|
||||||
|
|
|
@ -200,6 +200,8 @@ namespace fs
|
||||||
{
|
{
|
||||||
std::unique_ptr<file_base> m_file;
|
std::unique_ptr<file_base> m_file;
|
||||||
|
|
||||||
|
bool strict_read_check(u64 size, u64 type_size) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Default constructor
|
// Default constructor
|
||||||
file() = default;
|
file() = default;
|
||||||
|
@ -377,15 +379,24 @@ namespace fs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read std::basic_string
|
// Read std::basic_string
|
||||||
template <typename T>
|
template <bool IsStrict = false, typename T>
|
||||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str, usz size,
|
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str, usz _size,
|
||||||
const char* file = __builtin_FILE(),
|
const char* file = __builtin_FILE(),
|
||||||
const char* func = __builtin_FUNCTION(),
|
const char* func = __builtin_FUNCTION(),
|
||||||
u32 line = __builtin_LINE(),
|
u32 line = __builtin_LINE(),
|
||||||
u32 col = __builtin_COLUMN()) const
|
u32 col = __builtin_COLUMN()) const
|
||||||
{
|
{
|
||||||
str.resize(size);
|
if (!m_file) xnull({line, col, file, func});
|
||||||
return read(&str[0], size * sizeof(T), line, col, file, func) == size * sizeof(T);
|
if (!_size) return true;
|
||||||
|
|
||||||
|
if constexpr (IsStrict)
|
||||||
|
{
|
||||||
|
// If _size arg is too high std::bad_alloc may happen in resize and then we cannot error check
|
||||||
|
if (!strict_read_check(_size, sizeof(T))) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
str.resize(_size);
|
||||||
|
return read(str.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read POD, sizeof(T) is used
|
// Read POD, sizeof(T) is used
|
||||||
|
@ -412,15 +423,23 @@ namespace fs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read POD std::vector
|
// Read POD std::vector
|
||||||
template <typename T>
|
template <bool IsStrict = false, typename T>
|
||||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, usz size,
|
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, usz _size,
|
||||||
const char* file = __builtin_FILE(),
|
const char* file = __builtin_FILE(),
|
||||||
const char* func = __builtin_FUNCTION(),
|
const char* func = __builtin_FUNCTION(),
|
||||||
u32 line = __builtin_LINE(),
|
u32 line = __builtin_LINE(),
|
||||||
u32 col = __builtin_COLUMN()) const
|
u32 col = __builtin_COLUMN()) const
|
||||||
{
|
{
|
||||||
vec.resize(size);
|
if (!m_file) xnull({line, col, file, func});
|
||||||
return read(vec.data(), sizeof(T) * size, line, col, file, func) == sizeof(T) * size;
|
if (!_size) return true;
|
||||||
|
|
||||||
|
if constexpr (IsStrict)
|
||||||
|
{
|
||||||
|
if (!strict_read_check(_size, sizeof(T))) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec.resize(_size);
|
||||||
|
return read(vec.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read POD (experimental)
|
// Read POD (experimental)
|
||||||
|
|
|
@ -241,17 +241,15 @@ public:
|
||||||
|
|
||||||
if (!(opts & elf_opt::no_programs))
|
if (!(opts & elf_opt::no_programs))
|
||||||
{
|
{
|
||||||
_phdrs.resize(header.e_phnum);
|
|
||||||
stream.seek(offset + header.e_phoff);
|
stream.seek(offset + header.e_phoff);
|
||||||
if (!stream.read(_phdrs))
|
if (!stream.read<true>(_phdrs, header.e_phnum))
|
||||||
return set_error(elf_error::stream_phdrs);
|
return set_error(elf_error::stream_phdrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(opts & elf_opt::no_sections))
|
if (!(opts & elf_opt::no_sections))
|
||||||
{
|
{
|
||||||
shdrs.resize(header.e_shnum);
|
|
||||||
stream.seek(offset + header.e_shoff);
|
stream.seek(offset + header.e_shoff);
|
||||||
if (!stream.read(shdrs))
|
if (!stream.read<true>(shdrs, header.e_shnum))
|
||||||
return set_error(elf_error::stream_shdrs);
|
return set_error(elf_error::stream_shdrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,9 +263,8 @@ public:
|
||||||
|
|
||||||
if (!(opts & elf_opt::no_data))
|
if (!(opts & elf_opt::no_data))
|
||||||
{
|
{
|
||||||
progs.back().bin.resize(hdr.p_filesz);
|
|
||||||
stream.seek(offset + hdr.p_offset);
|
stream.seek(offset + hdr.p_offset);
|
||||||
if (!stream.read(progs.back().bin))
|
if (!stream.read<true>(progs.back().bin, hdr.p_filesz))
|
||||||
return set_error(elf_error::stream_data);
|
return set_error(elf_error::stream_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,23 +40,15 @@ pup_object::pup_object(fs::file&& file) : m_file(std::move(file))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr usz entry_size = sizeof(PUPFileEntry) + sizeof(PUPHashEntry);
|
if (!m_header.file_count)
|
||||||
|
|
||||||
if (!m_header.file_count || (file_size - sizeof(PUPHeader)) / entry_size < m_header.file_count)
|
|
||||||
{
|
{
|
||||||
// These checks before read() are to avoid some std::bad_alloc exceptions when file_count is too large
|
|
||||||
// So we cannot rely on read() for error checking in such cases
|
|
||||||
m_error = pup_error::header_file_count;
|
m_error = pup_error::header_file_count;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file_tbl.resize(m_header.file_count);
|
if (!m_file.read<true>(m_file_tbl, m_header.file_count) || !m_file.read<true>(m_hash_tbl, m_header.file_count))
|
||||||
m_hash_tbl.resize(m_header.file_count);
|
|
||||||
|
|
||||||
if (!m_file.read(m_file_tbl) || !m_file.read(m_hash_tbl))
|
|
||||||
{
|
{
|
||||||
// If these fail it is an unexpected filesystem error, because file size must suffice as we checked in previous checks
|
m_error = pup_error::header_file_count;
|
||||||
m_error = pup_error::file_entries;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,10 @@ bool TROPUSRLoader::LoadTableHeaders()
|
||||||
|
|
||||||
m_file.seek(0x30);
|
m_file.seek(0x30);
|
||||||
m_tableHeaders.clear();
|
m_tableHeaders.clear();
|
||||||
m_tableHeaders.resize(m_header.tables_count);
|
|
||||||
|
|
||||||
for (TROPUSRTableHeader& tableHeader : m_tableHeaders)
|
if (!m_file.read<true>(m_tableHeaders, m_header.tables_count))
|
||||||
{
|
{
|
||||||
if (!m_file.read(tableHeader))
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -77,25 +75,17 @@ bool TROPUSRLoader::LoadTables()
|
||||||
if (tableHeader.type == 4u)
|
if (tableHeader.type == 4u)
|
||||||
{
|
{
|
||||||
m_table4.clear();
|
m_table4.clear();
|
||||||
m_table4.resize(tableHeader.entries_count);
|
|
||||||
|
|
||||||
for (auto& entry : m_table4)
|
if (!m_file.read<true>(m_table4, tableHeader.entries_count))
|
||||||
{
|
return false;
|
||||||
if (!m_file.read(entry))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tableHeader.type == 6u)
|
if (tableHeader.type == 6u)
|
||||||
{
|
{
|
||||||
m_table6.clear();
|
m_table6.clear();
|
||||||
m_table6.resize(tableHeader.entries_count);
|
|
||||||
|
|
||||||
for (auto& entry : m_table6)
|
if (!m_file.read<true>(m_table6, tableHeader.entries_count))
|
||||||
{
|
return false;
|
||||||
if (!m_file.read(entry))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Other tables
|
// TODO: Other tables
|
||||||
|
|
|
@ -39,8 +39,8 @@ bool TRPLoader::Install(const std::string& dest, bool /*show*/)
|
||||||
for (const TRPEntry& entry : m_entries)
|
for (const TRPEntry& entry : m_entries)
|
||||||
{
|
{
|
||||||
trp_f.seek(entry.offset);
|
trp_f.seek(entry.offset);
|
||||||
buffer.resize(entry.size);
|
|
||||||
if (!trp_f.read(buffer))
|
if (!trp_f.read<true>(buffer, entry.size))
|
||||||
{
|
{
|
||||||
trp_log.error("Failed to read TRPEntry at: offset=0x%x, size=0x%x", entry.offset, entry.size);
|
trp_log.error("Failed to read TRPEntry at: offset=0x%x, size=0x%x", entry.offset, entry.size);
|
||||||
continue; // ???
|
continue; // ???
|
||||||
|
@ -103,10 +103,10 @@ bool TRPLoader::LoadHeader(bool show)
|
||||||
if (m_header.trp_version >= 2)
|
if (m_header.trp_version >= 2)
|
||||||
{
|
{
|
||||||
unsigned char hash[20];
|
unsigned char hash[20];
|
||||||
std::vector<unsigned char> file_contents(m_header.trp_file_size);
|
std::vector<u8> file_contents;
|
||||||
|
|
||||||
trp_f.seek(0);
|
trp_f.seek(0);
|
||||||
if (!trp_f.read(file_contents))
|
if (!trp_f.read<true>(file_contents, m_header.trp_file_size))
|
||||||
{
|
{
|
||||||
trp_log.notice("Failed verifying checksum");
|
trp_log.notice("Failed verifying checksum");
|
||||||
}
|
}
|
||||||
|
@ -126,18 +126,17 @@ bool TRPLoader::LoadHeader(bool show)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_entries.clear();
|
m_entries.clear();
|
||||||
m_entries.resize(m_header.trp_files_count);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < m_header.trp_files_count; i++)
|
if (!trp_f.read<true>(m_entries, m_header.trp_files_count))
|
||||||
{
|
{
|
||||||
if (!trp_f.read(m_entries[i]))
|
return false;
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (show)
|
if (show)
|
||||||
|
{
|
||||||
|
for (const auto& entry : m_entries)
|
||||||
{
|
{
|
||||||
trp_log.notice("TRP entry #%d: %s", m_entries[i].name);
|
trp_log.notice("TRP entry #%u: %s", &entry - m_entries.data(), entry.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue