From fff538e5637bd15eb5c47b50c48dabe1b1dbbdf2 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 5 Dec 2023 22:34:35 +0100 Subject: [PATCH] Core/Boot: Check bounds in Load_BS2(). --- Source/Core/Core/Boot/Boot.cpp | 36 ++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 5fc52585e0..324bc5de22 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -399,12 +400,20 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) constexpr u32 PAL_v1_0 = 0x4F319F43; constexpr u32 PAL_v1_2 = 0xAD1B7F16; - // Load the whole ROM dump - std::string data; - if (!File::ReadFileToString(boot_rom_filename, data)) - return false; + // Load the IPL ROM dump, limited to 2MiB which is the size of the official IPLs. + constexpr size_t max_ipl_size = 2 * 1024 * 1024; + std::vector data; + { + File::IOFile file(boot_rom_filename, "rb"); + if (!file) + return false; - const u32 ipl_hash = Common::ComputeCRC32(data); + data.resize(static_cast(std::min(file.GetSize(), max_ipl_size))); + if (!file.ReadArray(data.data(), data.size())) + return false; + } + + const u32 ipl_hash = Common::ComputeCRC32(data.data(), data.size()); bool known_ipl = false; bool pal_ipl = false; switch (ipl_hash) @@ -433,15 +442,26 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) } // Run the descrambler over the encrypted section containing BS1/BS2 - ExpansionInterface::CEXIIPL::Descrambler((u8*)data.data() + 0x100, 0x1AFE00); + if (data.size() > 0x100) + { + ExpansionInterface::CEXIIPL::Descrambler( + data.data() + 0x100, static_cast(std::min(data.size() - 0x100, 0x1AFE00))); + } // TODO: Execution is supposed to start at 0xFFF00000, not 0x81200000; // copying the initial boot code to 0x81200000 is a hack. // For now, HLE the first few instructions and start at 0x81200150 // to work around this. auto& memory = system.GetMemory(); - memory.CopyToEmu(0x01200000, data.data() + 0x100, 0x700); - memory.CopyToEmu(0x01300000, data.data() + 0x820, 0x1AFE00); + if (data.size() > 0x100) + { + memory.CopyToEmu(0x01200000, data.data() + 0x100, std::min(data.size() - 0x100, 0x700)); + } + if (data.size() > 0x820) + { + memory.CopyToEmu(0x01300000, data.data() + 0x820, + std::min(data.size() - 0x820, 0x1AFE00)); + } auto& ppc_state = system.GetPPCState(); ppc_state.gpr[3] = 0xfff0001f;