diff --git a/src/Emulator/Core/CPU/CPU.cpp b/src/Emulator/Core/CPU/CPU.cpp index 31d0f01e..472c15af 100644 --- a/src/Emulator/Core/CPU/CPU.cpp +++ b/src/Emulator/Core/CPU/CPU.cpp @@ -10,6 +10,7 @@ HyperCPU::CPU::CPU(std::uint16_t core_count, std::uint64_t mem_size, char* binar : mem_controller(dynamic_cast(new MemoryControllerST(mem_size, this))), core_count(core_count), total_mem(mem_size), + binary_size(binary_size), halted(false), ivt_initialized(false), io_ctl(std::make_unique()) { @@ -251,7 +252,7 @@ void HyperCPU::CPU::Run() { pending_interrupt.reset(); continue; } - + buffer = m_decoder->FetchAndDecode(); switch (buffer.m_opcode) { diff --git a/src/Emulator/Core/CPU/CPU.hpp b/src/Emulator/Core/CPU/CPU.hpp index 8899dfd8..36da7013 100644 --- a/src/Emulator/Core/CPU/CPU.hpp +++ b/src/Emulator/Core/CPU/CPU.hpp @@ -29,6 +29,7 @@ namespace HyperCPU { // Data std::uint16_t core_count; std::uint64_t total_mem; + std::uint64_t binary_size; bool halted; // General space for registers diff --git a/src/Emulator/Core/CPU/Interrupts/InterruptHandler.cpp b/src/Emulator/Core/CPU/Interrupts/InterruptHandler.cpp index 3c3ed6f5..09eeedb2 100644 --- a/src/Emulator/Core/CPU/Interrupts/InterruptHandler.cpp +++ b/src/Emulator/Core/CPU/Interrupts/InterruptHandler.cpp @@ -6,6 +6,11 @@ #include "PCH/CStd.hpp" void HyperCPU::CPU::TriggerInterrupt(HyperCPU::cpu_exceptions exception) { + if (*xip >= binary_size) { + spdlog::error("XIP exceeded the binary size, aborting!"); + std::abort(); + } + if (!ivt_initialized || pending_interrupt.has_value()) { spdlog::error("Interrupt was triggered, but failed to execute handler! XIP: {}", *xip); std::abort(); diff --git a/src/Emulator/Main.cpp b/src/Emulator/Main.cpp index a70fc7ac..80634cef 100644 --- a/src/Emulator/Main.cpp +++ b/src/Emulator/Main.cpp @@ -75,6 +75,45 @@ std::uint64_t ParseMemoryString(const std::string& str) { return result * multiplier; } +int VerifyBinaryFile(std::int64_t filesize, HyperCPU::GenericHeader header) { + if (filesize < sizeof(HyperCPU::GenericHeader)) { + spdlog::error("Invalid binary header! (excepted {} bytes, got {})", sizeof(HyperCPU::GenericHeader), filesize); + return 1; + } + + if (header.magic != HyperCPU::magic) { + spdlog::error("Invalid magic!"); + return 1; + } + + switch (header.version) { + case HyperCPU::Version::PreRelease: + case HyperCPU::Version::Release1_0: + break; + default: + spdlog::error("Invalid release field!"); + return 1; + } + + switch (header.type) { + case HyperCPU::FileType::Binary: + break; + case HyperCPU::FileType::Object: + spdlog::error("Executing object files is not supported, please link it first!"); + return 1; + default: + spdlog::error("Invalid type field!"); + return 1; + } + + if (filesize != (sizeof(HyperCPU::GenericHeader) + header.code_size)) { + spdlog::error("Invalid binary code! (expected {} bytes, got {})", header.code_size, (filesize - sizeof(HyperCPU::GenericHeader))); + return 1; + } + + return 0; +} + int main(int argc, char** argv) { #ifdef HCPU_ENABLE_LIBUNWIND global_bt_controller = BacktraceController(argv[0]); @@ -111,36 +150,21 @@ int main(int argc, char** argv) { } std::ifstream file(source); - std::int64_t binarysize = std::filesystem::file_size(source) - sizeof(HyperCPU::GenericHeader); - - HyperCPU::GenericHeader header = ParseHeader(file); - // Validate header contents - if (header.magic != HyperCPU::magic) { - spdlog::error("Invalid magic!"); + if (std::filesystem::file_size(source) < sizeof(HyperCPU::GenericHeader)) { + spdlog::error("The binary file is too small! (No binary header?)"); return 1; } + + std::int64_t filesize = std::filesystem::file_size(source); + std::int64_t binarysize = filesize - sizeof(HyperCPU::GenericHeader); - switch (header.version) { - case HyperCPU::Version::PreRelease: - case HyperCPU::Version::Release1_0: - break; - default: - spdlog::error("Invalid release field!"); - return 1; - } + HyperCPU::GenericHeader header = ParseHeader(file); - switch (header.type) { - case HyperCPU::FileType::Binary: - break; - case HyperCPU::FileType::Object: - spdlog::error("Executing object files is not supported, please link it first!"); - return 1; - default: - spdlog::error("Invalid type field!"); + if (VerifyBinaryFile(filesize, header)) { return 1; } - + std::unique_ptr buf(new char[binarysize]); file.read(buf.get(), binarysize); diff --git a/tests/fixtures.hpp b/tests/fixtures.hpp index 12c80ce3..aa8257b2 100644 --- a/tests/fixtures.hpp +++ b/tests/fixtures.hpp @@ -92,7 +92,7 @@ class CPU_TEST : public ::testing::Test { HyperCPU::CPU cpu; CPU_TEST() - : cpu(1, 4096) { + : cpu(1, 4096, nullptr, 4096) { } }; @@ -131,7 +131,7 @@ class EXCEPTION_TEST : public ::testing::Test { HyperCPU::CPU cpu; EXCEPTION_TEST() - : cpu(1, 4096) { + : cpu(1, 4096, nullptr, 4096) { } virtual void SetUp() {