From 09ead1b6eac724f99eefe1ed6dd272ff34e1ab76 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 4 Aug 2024 12:21:07 +0200 Subject: [PATCH] Dimensions: try to fix out of bounds array access --- rpcs3/Emu/Io/Dimensions.cpp | 49 +++++++++++++++++++++++-------------- rpcs3/Emu/Io/Dimensions.h | 4 ++- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/Io/Dimensions.cpp b/rpcs3/Emu/Io/Dimensions.cpp index 9fc8480bde..9784894478 100644 --- a/rpcs3/Emu/Io/Dimensions.cpp +++ b/rpcs3/Emu/Io/Dimensions.cpp @@ -294,17 +294,21 @@ void dimensions_toypad::query_block(u8 index, u8 page, std::array& reply { std::lock_guard lock(m_dimensions_mutex); - // Index from game begins at 1 rather than 0, so minus 1 here - const dimensions_figure& figure = get_figure_by_index(index - 1); - reply_buf[0] = 0x55; reply_buf[1] = 0x12; reply_buf[2] = sequence; reply_buf[3] = 0x00; - // Query 4 pages of 4 bytes from the figure, copy this to the response - if (figure.index != 255 && (4 * page) < ((0x2D * 4) - 16)) + + // Index from game begins at 1 rather than 0, so minus 1 here + if (const u8 figure_index = index - 1; figure_index < dimensions_figure_count) { - std::memcpy(&reply_buf[4], figure.data.data() + (4 * page), 16); + const dimensions_figure& figure = get_figure_by_index(figure_index); + + // Query 4 pages of 4 bytes from the figure, copy this to the response + if (figure.index != 255 && (4 * page) < ((0x2D * 4) - 16)) + { + std::memcpy(&reply_buf[4], figure.data.data() + (4 * page), 16); + } } reply_buf[20] = generate_checksum(reply_buf, 20); } @@ -313,23 +317,27 @@ void dimensions_toypad::write_block(u8 index, u8 page, const u8* to_write_buf, s { std::lock_guard lock(m_dimensions_mutex); - // Index from game begins at 1 rather than 0, so minus 1 here - dimensions_figure& figure = get_figure_by_index(index - 1); - reply_buf[0] = 0x55; reply_buf[1] = 0x02; reply_buf[2] = sequence; reply_buf[3] = 0x00; - // Copy 4 bytes to the page on the figure requested by the game - if (figure.index != 255 && page < 0x2D) + + // Index from game begins at 1 rather than 0, so minus 1 here + if (const u8 figure_index = index - 1; figure_index < dimensions_figure_count) { - // Id is written to page 36 - if (page == 36) + dimensions_figure& figure = get_figure_by_index(figure_index); + + // Copy 4 bytes to the page on the figure requested by the game + if (figure.index != 255 && page < 0x2D) { - figure.id = read_from_ptr>(to_write_buf); + // Id is written to page 36 + if (page == 36) + { + figure.id = read_from_ptr>(to_write_buf); + } + std::memcpy(figure.data.data() + (page * 4), to_write_buf, 4); + figure.save(); } - std::memcpy(figure.data.data() + (page * 4), to_write_buf, 4); - figure.save(); } reply_buf[4] = generate_checksum(reply_buf, 4); } @@ -340,11 +348,14 @@ void dimensions_toypad::get_model(const u8* buf, u8 sequence, std::array const std::array value = decrypt(buf, std::nullopt); const u8 index = value[0]; const u32 conf = read_from_ptr>(value, 4); - // Index from game begins at 1 rather than 0, so minus 1 here - const dimensions_figure& figure = get_figure_by_index(index - 1); std::array value_to_encrypt = {}; // Response is the figure's id (little endian) followed by the confirmation from payload - write_to_ptr>(value_to_encrypt, figure.id); + // Index from game begins at 1 rather than 0, so minus 1 here + if (const u8 figure_index = index - 1; figure_index < dimensions_figure_count) + { + const dimensions_figure& figure = get_figure_by_index(figure_index); + write_to_ptr>(value_to_encrypt, figure.id); + } write_to_ptr>(value_to_encrypt, 4, conf); const std::array encrypted = encrypt(value_to_encrypt.data(), std::nullopt); reply_buf[0] = 0x55; diff --git a/rpcs3/Emu/Io/Dimensions.h b/rpcs3/Emu/Io/Dimensions.h index 25117ef275..ab24928d0e 100644 --- a/rpcs3/Emu/Io/Dimensions.h +++ b/rpcs3/Emu/Io/Dimensions.h @@ -6,6 +6,8 @@ #include #include +static constexpr size_t dimensions_figure_count = 7; + struct dimensions_figure { fs::file dim_file; @@ -35,7 +37,7 @@ public: protected: shared_mutex m_dimensions_mutex; - std::array m_figures; + std::array m_figures; private: static void random_uid(u8* uid_buffer);