diff --git a/core/libs/SceTypes.hpp b/core/libs/SceTypes.hpp index 3f73232949..5d4088a540 100644 --- a/core/libs/SceTypes.hpp +++ b/core/libs/SceTypes.hpp @@ -1467,7 +1467,13 @@ struct SaveDataSearchInfo { std::uint8_t reserved[32]; }; static_assert(sizeof(SaveDataSearchInfo) == 48); -struct SaveDataMemoryData { void* buf; std::size_t buf_size; std::size_t offset; }; +struct SaveDataMemoryData { + void* buf; + std::size_t buf_size; + std::size_t offset; + std::uint8_t reserved[40]; +}; +static_assert(sizeof(SaveDataMemoryData) == 64); struct SaveDataMount3 { int user_id; diff --git a/core/libs/prx/libSceSaveData/SaveDataCore.hpp b/core/libs/prx/libSceSaveData/SaveDataCore.hpp index 200b607716..4705d8d62e 100644 --- a/core/libs/prx/libSceSaveData/SaveDataCore.hpp +++ b/core/libs/prx/libSceSaveData/SaveDataCore.hpp @@ -106,14 +106,6 @@ constexpr char SD_MEMORY_PREFIX[] = "sce_sdmemory"; constexpr std::size_t SD_MOUNT_PREFIX_LEN = sizeof(SD_ROOT_GUEST); constexpr std::size_t SD_MOUNT_POINT_CAPACITY = sizeof(SaveDataMountPoint) - SD_MOUNT_PREFIX_LEN - 1; -struct MemoryData { - void* buf; - std::size_t buf_size; - std::int64_t offset; - std::uint8_t reserved[40]; -}; -static_assert(sizeof(MemoryData) == 64, "SceSaveDataMemoryData is 64 bytes"); - struct MemorySync { std::int32_t user_id; std::uint32_t slot_id; @@ -873,10 +865,8 @@ std::filesystem::path memory_directory(std::int32_t user_id, std::uint32_t slot_ return save_root() / name / std::to_string(static_cast(user_id)); } -bool valid_memory_range(const MemoryData& data, std::size_t size) { - return data.buf != nullptr && data.offset >= 0 && - static_cast(data.offset) <= size && - data.buf_size <= size - static_cast(data.offset); +bool valid_memory_range(const SaveDataMemoryData& data, std::size_t size) { + return data.buf != nullptr && data.offset <= size && data.buf_size <= size - data.offset; } int setup_memory_internal(const SaveDataMemorySetup2* setup, SaveDataMemorySetupResult* result, @@ -959,14 +949,14 @@ int get_memory_internal(SaveDataMemoryGet2* get_param) { } const MemorySlot& slot = it->second; if (get_param->data != nullptr && - !valid_memory_range(*reinterpret_cast(get_param->data), slot.data.size())) { + !valid_memory_range(*get_param->data, slot.data.size())) { return SD_ERROR_PARAMETER; } if (get_param->param != nullptr && (slot.option & SD_MEMORY_SET_PARAM) == 0) { return SD_ERROR_PARAMETER; } if (get_param->data != nullptr) { - const MemoryData& data = *reinterpret_cast(get_param->data); + const SaveDataMemoryData& data = *get_param->data; std::memcpy(data.buf, slot.data.data() + data.offset, data.buf_size); } if (get_param->param != nullptr) { @@ -1001,7 +991,7 @@ int set_memory_internal(const SaveDataMemorySet2* set_param) { } const std::uint32_t count = set_param->data != nullptr && set_param->data_num == 0 ? 1u : set_param->data_num; - const MemoryData* descriptors = reinterpret_cast(set_param->data); + const SaveDataMemoryData* descriptors = set_param->data; for (std::uint32_t i = 0; i < count; i++) { if (!valid_memory_range(descriptors[i], it->second.data.size())) { return SD_ERROR_PARAMETER; @@ -1009,7 +999,7 @@ int set_memory_internal(const SaveDataMemorySet2* set_param) { } MemorySlot updated = it->second; for (std::uint32_t i = 0; i < count; i++) { - const MemoryData& data = descriptors[i]; + const SaveDataMemoryData& data = descriptors[i]; std::memcpy(updated.data.data() + data.offset, data.buf, data.buf_size); } if (set_param->param != nullptr) { diff --git a/core/libs/tests/SaveDataMemoryMetadata.cpp b/core/libs/tests/SaveDataMemoryMetadata.cpp index 8f40cccf5c..1c6f0f10e6 100644 --- a/core/libs/tests/SaveDataMemoryMetadata.cpp +++ b/core/libs/tests/SaveDataMemoryMetadata.cpp @@ -2,8 +2,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -116,6 +118,24 @@ int main() { Require(sceSaveDataSetSaveDataMemory2(&set) == 0); std::copy(first.begin(), first.end(), memoryExpected.begin() + 4); Require(Read(memoryPath) == memoryExpected); + std::array third{'p', 'q', 'r', 's'}; + std::array fourth{'t', 'u', 'v', 'w'}; + constexpr std::size_t GuestMemoryDataSize = 64; + alignas(SaveDataMemoryData) std::array guestData{}; + const auto putGuestData = [&guestData](std::size_t index, const char* buffer, std::uint64_t size, std::uint64_t offset) { + unsigned char* entry = guestData.data() + index * GuestMemoryDataSize; + std::memcpy(entry, &buffer, sizeof(buffer)); + std::memcpy(entry + 8, &size, sizeof(size)); + std::memcpy(entry + 16, &offset, sizeof(offset)); + }; + putGuestData(0, third.data(), third.size(), 0); + putGuestData(1, fourth.data(), fourth.size(), 16); + set.data = reinterpret_cast(guestData.data()); + set.data_num = 2; + Require(sceSaveDataSetSaveDataMemory2(&set) == 0); + std::copy(third.begin(), third.end(), memoryExpected.begin()); + std::copy(fourth.begin(), fourth.end(), memoryExpected.begin() + 16); + Require(Read(memoryPath) == memoryExpected); const auto setupParamPath = std::filesystem::path("_sd_mem/u42/slot0.param"); const auto setupBinPath = std::filesystem::path("_sd_mem/u42/slot0.bin"); const auto setupParamTemp = setupParamPath.string() + ".tmp";