GameList: Fix scanning of ELF files

This commit is contained in:
Stenzek 2024-12-01 13:10:20 +10:00
parent 9dec34c8c0
commit 145ad2db27
No known key found for this signature in database
3 changed files with 48 additions and 3 deletions

View File

@ -11,6 +11,7 @@
#include "system.h"
#include "util/cd_image.h"
#include "util/elf_file.h"
#include "util/http_downloader.h"
#include "util/image.h"
#include "util/ini_settings_interface.h"
@ -199,6 +200,18 @@ bool GameList::GetExeListEntry(const std::string& path, GameList::Entry* entry)
// Who knows
entry->region = DiscRegion::Other;
}
else if (StringUtil::EndsWithNoCase(filename, ".elf"))
{
ELFFile::Elf32_Ehdr header;
if (std::fread(&header, sizeof(header), 1, fp.get()) != 1 || !ELFFile::IsValidElfHeader(header))
{
WARNING_LOG("{} is not a valid ELF.", path);
return false;
}
// Who knows
entry->region = DiscRegion::Other;
}
else
{
BIOS::PSEXEHeader header;

View File

@ -9,6 +9,7 @@
LOG_CHANNEL(FileLoader);
static constexpr const u8 EXPECTED_ELF_HEADER[4] = {'\177', 'E', 'L', 'F'};
static constexpr s64 MAX_ELF_FILE_SIZE = 32 * 1024 * 1024;
ELFFile::ELFFile() = default;
@ -113,9 +114,8 @@ bool ELFFile::Open(DataArray data, Error* error)
{
m_data = std::move(data);
static constexpr const u8 EXPECTED_HEADER[4] = {'\177', 'E', 'L', 'F'};
if (m_data.size() < sizeof(Elf32_Ehdr) || std::memcmp(m_data.data(), EXPECTED_HEADER, sizeof(EXPECTED_HEADER)) != 0)
if (m_data.size() < sizeof(Elf32_Ehdr) ||
std::memcmp(m_data.data(), EXPECTED_ELF_HEADER, sizeof(EXPECTED_ELF_HEADER)) != 0)
{
Error::SetStringView(error, "Invalid header.");
return false;
@ -202,3 +202,32 @@ bool ELFFile::LoadExecutableSections(const LoadExecutableSectionCallback& callba
return true;
}
bool ELFFile::IsValidElfHeader(const std::span<const u8> data, Error* error /*= nullptr*/)
{
if (data.size() < sizeof(Elf32_Ehdr))
{
Error::SetStringView(error, "Invalid header.");
return false;
}
return IsValidElfHeader(reinterpret_cast<const Elf32_Ehdr&>(*data.data()), error);
}
bool ELFFile::IsValidElfHeader(const Elf32_Ehdr& header, Error* error /* = nullptr */)
{
if (std::memcmp(header.e_ident, EXPECTED_ELF_HEADER, sizeof(EXPECTED_ELF_HEADER)) != 0)
{
Error::SetStringView(error, "Invalid header.");
return false;
}
if (header.e_machine != EM_MIPS)
{
Error::SetStringFmt(error, "Unsupported machine type {}.", header.e_machine);
return false;
}
// probably fine
return true;
}

View File

@ -94,6 +94,9 @@ public:
ELFFile();
~ELFFile();
static bool IsValidElfHeader(const std::span<const u8> data, Error* error = nullptr);
static bool IsValidElfHeader(const Elf32_Ehdr& header, Error* error = nullptr);
const Elf32_Ehdr& GetELFHeader() const;
u32 GetEntryPoint() const;