From 35c77abbc252007cf0cf5318262794ba852eb347 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 9 May 2015 16:49:18 +0200 Subject: [PATCH] DOL loader cleanup with std::vector and safety checks --- Source/Core/Core/Boot/Boot.cpp | 5 +- Source/Core/Core/Boot/Boot_DOL.cpp | 119 +++++++++--------- Source/Core/Core/Boot/Boot_DOL.h | 18 +-- Source/Core/Core/Boot/Boot_WiiWAD.cpp | 3 + .../Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 16 ++- 5 files changed, 87 insertions(+), 74 deletions(-) diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index f89324e847..fc85dfe6c2 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -233,7 +233,7 @@ bool CBoot::BootUp() DVDInterface::SetVolumeName(_StartupPara.m_strFilename); DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid()); if (!DVDInterface::VolumeIsValid()) - break; + return false; const DiscIO::IVolume& pVolume = DVDInterface::GetVolume(); @@ -296,6 +296,9 @@ bool CBoot::BootUp() case SCoreStartupParameter::BOOT_DOL: { CDolLoader dolLoader(_StartupPara.m_strFilename); + if (!dolLoader.IsValid()) + return false; + // Check if we have gotten a Wii file or not bool dolWii = dolLoader.IsWii(); if (dolWii != _StartupPara.bWii) diff --git a/Source/Core/Core/Boot/Boot_DOL.cpp b/Source/Core/Core/Boot/Boot_DOL.cpp index fbfa70e0c1..373d77ef06 100644 --- a/Source/Core/Core/Boot/Boot_DOL.cpp +++ b/Source/Core/Core/Boot/Boot_DOL.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "Common/CommonFuncs.h" #include "Common/FileUtil.h" @@ -11,106 +12,100 @@ #include "Core/HW/Memmap.h" #include "Core/PowerPC/PowerPC.h" -CDolLoader::CDolLoader(u8* _pBuffer, u32 _Size) - : m_isWii(false) +CDolLoader::CDolLoader(u8* buffer, size_t size) { - Initialize(_pBuffer, _Size); + m_is_valid = Initialize(buffer, size); } CDolLoader::CDolLoader(const std::string& filename) - : m_isWii(false) { const u64 size = File::GetSize(filename); - u8* const tmpBuffer = new u8[(size_t)size]; + std::vector temp_buffer(size); { File::IOFile pStream(filename, "rb"); - pStream.ReadBytes(tmpBuffer, (size_t)size); + pStream.ReadBytes(temp_buffer.data(), temp_buffer.size()); } - Initialize(tmpBuffer, (u32)size); - delete[] tmpBuffer; + m_is_valid = Initialize(temp_buffer.data(), temp_buffer.size()); } CDolLoader::~CDolLoader() { - for (auto& sect : text_section) - { - delete [] sect; - sect = nullptr; - } - - for (auto& sect : data_section) - { - delete [] sect; - sect = nullptr; - } } -void CDolLoader::Initialize(u8* _pBuffer, u32 _Size) +bool CDolLoader::Initialize(u8* buffer, size_t size) { - memcpy(&m_dolheader, _pBuffer, sizeof(SDolHeader)); + if (size < sizeof(SDolHeader)) + return false; + + memcpy(&m_dolheader, buffer, sizeof(SDolHeader)); // swap memory u32* p = (u32*)&m_dolheader; - for (size_t i = 0; i < (sizeof(SDolHeader)/sizeof(u32)); i++) + for (size_t i = 0; i < (sizeof(SDolHeader) / sizeof(u32)); i++) p[i] = Common::swap32(p[i]); - for (auto& sect : text_section) - sect = nullptr; - for (auto& sect : data_section) - sect = nullptr; + const u32 HID4_pattern = Common::swap32(0x7c13fba6); + const u32 HID4_mask = Common::swap32(0xfc1fffff); - u32 HID4_pattern = 0x7c13fba6; - u32 HID4_mask = 0xfc1fffff; + m_is_wii = false; - for (int i = 0; i < DOL_NUM_TEXT; i++) + m_text_sections.reserve(DOL_NUM_TEXT); + for (int i = 0; i < DOL_NUM_TEXT; ++i) { - if (m_dolheader.textOffset[i] != 0) + if (m_dolheader.textSize[i] != 0) { - text_section[i] = new u8[m_dolheader.textSize[i]]; - memcpy(text_section[i], _pBuffer + m_dolheader.textOffset[i], m_dolheader.textSize[i]); - for (unsigned int j = 0; j < (m_dolheader.textSize[i]/sizeof(u32)); j++) + if (size < m_dolheader.textOffset[i] + m_dolheader.textSize[i]) + return false; + + u8* text_start = buffer + m_dolheader.textOffset[i]; + m_text_sections.emplace_back(text_start, text_start + m_dolheader.textSize[i]); + + for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j) { - u32 word = Common::swap32(((u32*)text_section[i])[j]); + u32 word = ((u32*)text_start)[j]; if ((word & HID4_mask) == HID4_pattern) - { - m_isWii = true; - break; - } + m_is_wii = true; } } - } - - for (int i = 0; i < DOL_NUM_DATA; i++) - { - if (m_dolheader.dataOffset[i] != 0) + else { - data_section[i] = new u8[m_dolheader.dataSize[i]]; - memcpy(data_section[i], _pBuffer + m_dolheader.dataOffset[i], m_dolheader.dataSize[i]); + // Make sure that m_text_sections indexes match header indexes + m_text_sections.emplace_back(); } } + + m_data_sections.reserve(DOL_NUM_DATA); + for (int i = 0; i < DOL_NUM_DATA; ++i) + { + if (m_dolheader.dataSize[i] != 0) + { + if (size < m_dolheader.dataOffset[i] + m_dolheader.dataSize[i]) + return false; + + u8* data_start = buffer + m_dolheader.dataOffset[i]; + m_data_sections.emplace_back(data_start, data_start + m_dolheader.dataSize[i]); + } + else + { + // Make sure that m_data_sections indexes match header indexes + m_data_sections.emplace_back(); + } + } + + return true; } -void CDolLoader::Load() +void CDolLoader::Load() const { // load all text (code) sections - for (int i = 0; i < DOL_NUM_TEXT; i++) - { - if (m_dolheader.textOffset[i] != 0) - { - for (u32 num = 0; num < m_dolheader.textSize[i]; num++) - Memory::Write_U8(text_section[i][num], m_dolheader.textAddress[i] + num); - } - } + for (size_t i = 0; i < m_text_sections.size(); ++i) + if (!m_text_sections[i].empty()) + Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(), m_text_sections[i].size()); // load all data sections - for (int i = 0; i < DOL_NUM_DATA; i++) - { - if (m_dolheader.dataOffset[i] != 0) - { - for (u32 num = 0; num < m_dolheader.dataSize[i]; num++) - Memory::Write_U8(data_section[i][num], m_dolheader.dataAddress[i] + num); - } - } + for (size_t i = 0; i < m_data_sections.size(); ++i) + if (!m_data_sections[i].empty()) + Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(), m_data_sections[i].size()); } diff --git a/Source/Core/Core/Boot/Boot_DOL.h b/Source/Core/Core/Boot/Boot_DOL.h index 60f1b8d46f..7a51879604 100644 --- a/Source/Core/Core/Boot/Boot_DOL.h +++ b/Source/Core/Core/Boot/Boot_DOL.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "Common/CommonTypes.h" @@ -12,14 +13,15 @@ class CDolLoader { public: CDolLoader(const std::string& filename); - CDolLoader(u8* _pBuffer, u32 _Size); + CDolLoader(u8* buffer, size_t size); ~CDolLoader(); - bool IsWii() const { return m_isWii; } + bool IsValid() const { return m_is_valid; } + bool IsWii() const { return m_is_wii; } u32 GetEntryPoint() const { return m_dolheader.entryPoint; } // Load into emulated memory - void Load(); + void Load() const; private: enum @@ -42,15 +44,15 @@ private: u32 bssAddress; u32 bssSize; u32 entryPoint; - u32 padd[7]; }; SDolHeader m_dolheader; - u8 *data_section[DOL_NUM_DATA]; - u8 *text_section[DOL_NUM_TEXT]; + std::vector> m_data_sections; + std::vector> m_text_sections; - bool m_isWii; + bool m_is_valid; + bool m_is_wii; // Copy sections to internal buffers - void Initialize(u8* _pBuffer, u32 _Size); + bool Initialize(u8* buffer, size_t size); }; diff --git a/Source/Core/Core/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Boot/Boot_WiiWAD.cpp index d06c278da3..1ab9f70f38 100644 --- a/Source/Core/Core/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Boot/Boot_WiiWAD.cpp @@ -106,6 +106,9 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename) { pDolLoader = std::make_unique(pContent->m_Filename); } + if (!pDolLoader->IsValid()) + return false; + pDolLoader->Load(); PC = pDolLoader->GetEntryPoint(); diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp index e827a2a308..b0400f18c2 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -924,10 +924,20 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) { pDolLoader = std::make_unique(pContent->m_Filename); } - pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly - PC = pDolLoader->GetEntryPoint(); + + if (pDolLoader->IsValid()) + { + pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly + PC = pDolLoader->GetEntryPoint(); + bSuccess = true; + } + else + { + PanicAlertT("IOCTL_ES_LAUNCH: The DOL file is invalid!"); + bSuccess = false; + } + IOSv = ContentLoader.GetIosVersion(); - bSuccess = true; } } }