From 88ba3c47c2e615442a36e335c03e3f27354e32d0 Mon Sep 17 00:00:00 2001 From: Eladash <18193363+elad335@users.noreply.github.com> Date: Thu, 15 Feb 2024 13:55:08 +0200 Subject: [PATCH] ELF.h: Avoid using seek operations --- Utilities/File.cpp | 4 ++-- Utilities/File.h | 16 ++++++++++------ rpcs3/Loader/ELF.h | 33 ++++++++++++++++++++------------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index b576992163..057b8a1191 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -1941,9 +1941,9 @@ bool fs::dir::open(const std::string& path) return true; } -bool fs::file::strict_read_check(u64 _size, u64 type_size) const +bool fs::file::strict_read_check(u64 offset, u64 _size, u64 type_size) const { - if (usz pos0 = pos(), size0 = size(); (pos0 >= size0 ? 0 : (size0 - pos0)) / type_size < _size) + if (usz pos0 = offset, size0 = size(); (pos0 >= size0 ? 0 : (size0 - pos0)) / type_size < _size) { fs::g_tls_error = fs::error::inval; return false; diff --git a/Utilities/File.h b/Utilities/File.h index 448fb24a4d..a2b21a5ff9 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -314,7 +314,7 @@ namespace fs } // Check if the handle is capable of reading (size * type_size) of bytes at the time of calling - bool strict_read_check(u64 size, u64 type_size = 1) const; + bool strict_read_check(u64 offset, u64 size, u64 type_size) const; // Read the data from the file and return the amount of data written in buffer u64 read(void* buffer, u64 count, @@ -432,7 +432,7 @@ namespace fs if (_size != umax) { // If _size arg is too high std::bad_alloc may happen during resize and then we cannot error check - if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(_size, sizeof(T))) + if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(pos(), _size, sizeof(T))) { return false; } @@ -457,7 +457,7 @@ namespace fs // Read POD std::vector template requires (std::is_trivially_copyable_v && !std::is_pointer_v) - bool read(std::vector& vec, usz _size = umax, + bool read(std::vector& vec, usz _size = umax, bool use_offs = false, usz offset = umax, const char* file = __builtin_FILE(), const char* func = __builtin_FUNCTION(), u32 line = __builtin_LINE(), @@ -468,7 +468,7 @@ namespace fs if (_size != umax) { // If _size arg is too high std::bad_alloc may happen during resize and then we cannot error check - if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(_size, sizeof(T))) + if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(use_offs ? offset : pos(), _size, sizeof(T))) { return false; } @@ -476,6 +476,11 @@ namespace fs vec.resize(_size); } + if (use_offs) + { + return read_at(offset, vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size(); + } + return read(vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size(); } @@ -518,8 +523,7 @@ namespace fs { std::vector result; result.resize(size() / sizeof(T)); - seek(0); - if (!read(result, result.size(), file, func, line, col)) xfail({line, col, file, func}); + if (!read(result, result.size(), true, 0, file, func, line, col)) xfail({line, col, file, func}); return result; } diff --git a/rpcs3/Loader/ELF.h b/rpcs3/Loader/ELF.h index 82dfed01cd..1090fb30ef 100644 --- a/rpcs3/Loader/ELF.h +++ b/rpcs3/Loader/ELF.h @@ -279,8 +279,8 @@ public: return set_error(elf_error::stream); // Read ELF header - stream.seek(offset); - if (!stream.read(header)) + highest_offset = sizeof(header); + if (sizeof(header) != stream.read_at(offset, &header, sizeof(header))) return set_error(elf_error::stream_header); // Check magic @@ -321,20 +321,24 @@ public: std::vector _phdrs; std::vector _shdrs; + u64 seek_pos = 0; + if (!(opts & elf_opt::no_programs)) { - stream.seek(offset + header.e_phoff); - if (!stream.read(_phdrs, header.e_phnum)) + seek_pos = offset + header.e_phoff; + highest_offset = std::max(highest_offset, seek_pos); + + if (!stream.read(_phdrs, header.e_phnum, true, seek_pos)) return set_error(elf_error::stream_phdrs); - highest_offset = std::max(highest_offset, stream.pos()); } if (!(opts & elf_opt::no_sections)) { - stream.seek(offset + header.e_shoff); - if (!stream.read(_shdrs, header.e_shnum)) + seek_pos = offset + header.e_shoff; + highest_offset = std::max(highest_offset, seek_pos); + + if (!stream.read(_shdrs, header.e_shnum, true, seek_pos)) return set_error(elf_error::stream_shdrs); - highest_offset = std::max(highest_offset, stream.pos()); } progs.clear(); @@ -345,10 +349,11 @@ public: if (!(opts & elf_opt::no_data)) { - stream.seek(offset + hdr.p_offset); - if (!stream.read(progs.back().bin, hdr.p_filesz)) + seek_pos = offset + hdr.p_offset; + highest_offset = std::max(highest_offset, seek_pos); + + if (!stream.read(progs.back().bin, hdr.p_filesz, true, seek_pos)) return set_error(elf_error::stream_data); - highest_offset = std::max(highest_offset, stream.pos()); } } @@ -380,8 +385,10 @@ public: continue; } - stream.seek(offset + shdr.sh_offset); - if (!stream.read(shdrs.back().bin, shdr.sh_size)) + seek_pos = offset + shdr.sh_offset; + highest_offset = std::max(highest_offset, seek_pos); + + if (!stream.read(shdrs.back().bin, shdr.sh_size, true, seek_pos)) return set_error(elf_error::stream_data); } }