Skip to content

Commit

Permalink
GameList: Fix scanning of ELF files
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Dec 1, 2024
1 parent 9dec34c commit 145ad2d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
13 changes: 13 additions & 0 deletions src/core/game_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
35 changes: 32 additions & 3 deletions src/util/elf_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
3 changes: 3 additions & 0 deletions src/util/elf_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class ELFFile
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;

Expand Down

0 comments on commit 145ad2d

Please sign in to comment.