From 3617f12a1e8fcf9b95f935640ca6939ba5a1eaf8 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 19 Jan 2020 04:25:50 +0300 Subject: [PATCH] sys_fs: avoid possible out of memory on file reads/writes Use fixed-sized intermediate buffer. --- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index e3cc526eaf..acf69c0f22 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -89,18 +89,48 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename) u64 lv2_file::op_read(vm::ptr buf, u64 size) { // Copy data from intermediate buffer (avoid passing vm pointer to a native API) - std::unique_ptr local_buf(new u8[size]); - const u64 result = file.read(local_buf.get(), size); - std::memcpy(buf.get_ptr(), local_buf.get(), result); + uchar local_buf[65536]; + + u64 result = 0; + + while (result < size) + { + const u64 block = std::min(size - result, sizeof(local_buf)); + const u64 nread = file.read(+local_buf, block); + + std::memcpy(static_cast(buf.get_ptr()) + result, local_buf, nread); + result += nread; + + if (nread < block) + { + break; + } + } + return result; } u64 lv2_file::op_write(vm::cptr buf, u64 size) { // Copy data to intermediate buffer (avoid passing vm pointer to a native API) - std::unique_ptr local_buf(new u8[size]); - std::memcpy(local_buf.get(), buf.get_ptr(), size); - return file.write(local_buf.get(), size); + uchar local_buf[65536]; + + u64 result = 0; + + while (result < size) + { + const u64 block = std::min(size - result, sizeof(local_buf)); + std::memcpy(local_buf, static_cast(buf.get_ptr()), block); + const u64 nwrite = file.write(+local_buf, block); + result += nwrite; + + if (nwrite < block) + { + break; + } + } + + return result; } struct lv2_file::file_view : fs::file_base