From 2a0b99d9f97e48427d6590bd998f9173f469272c Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 29 Oct 2021 15:41:25 -0700 Subject: [PATCH] sprofile: fix off-by-one in struct definition, fix GetImportableProfileUrls --- .../sprofile_srv_i_service_for_bg_agent.hpp | 8 ++-- .../srv/sprofile_srv_profile_manager.cpp | 2 +- .../srv/sprofile_srv_service_for_bg_agent.cpp | 18 ++++--- .../srv/sprofile_srv_service_for_bg_agent.hpp | 2 +- .../sprofile/srv/sprofile_srv_types.hpp | 47 ++++++++++++++++--- 5 files changed, 59 insertions(+), 18 deletions(-) diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp index 5e9612d91..985202c80 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp @@ -18,9 +18,9 @@ #include "sprofile_srv_i_profile_importer.hpp" #define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileImporter, (sf::Out> out), (out)) \ - AMS_SF_METHOD_INFO(C, H, 200, Result, GetMetadataEntryData, (sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \ - AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out out, sprofile::Identifier revision_key), (out, revision_key)) \ - AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ()) + AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileImporter, (sf::Out> out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 200, Result, GetImportableProfileUrls, (sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \ + AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out out, sprofile::Identifier revision_key), (out, revision_key)) \ + AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ()) AMS_SF_DEFINE_INTERFACE(ams::sprofile, ISprofileServiceForBgAgent, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO) diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp index 899bf3318..f414d5666 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp @@ -260,7 +260,7 @@ namespace ams::sprofile::srv { crypto::Md5Generator md5; md5.Update(std::addressof(import.header), sizeof(import.header)); md5.Update(std::addressof(import.metadata), sizeof(import.metadata)); - md5.Update(std::addressof(import.entries), sizeof(import.entries[0]) * std::min(import.metadata.num_entries, util::size(import.metadata.entries))); + md5.Update(std::addressof(import.profile_urls), sizeof(import.profile_urls[0]) * std::min(import.metadata.num_entries, util::size(import.metadata.entries))); u8 hash[crypto::Md5Generator::HashSize]; md5.GetHash(hash, sizeof(hash)); diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp index 62653d13a..fad4893d0 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp @@ -34,7 +34,7 @@ namespace ams::sprofile::srv { return ResultSuccess(); } - Result ServiceForBgAgent::GetMetadataEntryData(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg) { + Result ServiceForBgAgent::GetImportableProfileUrls(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg) { /* Check size. */ R_UNLESS(out.GetSize() >= arg.metadata.num_entries, sprofile::ResultInvalidArgument()); @@ -42,25 +42,31 @@ namespace ams::sprofile::srv { sprofile::srv::ProfileMetadata primary_metadata; R_TRY_CATCH(m_profile_manager->LoadPrimaryMetadata(std::addressof(primary_metadata))) { R_CATCH(fs::ResultPathNotFound) { - /* If we have no metadata, we can't get any entries. */ - *out_count = 0; - return ResultSuccess(); + /* It's okay if we have no primary metadata -- this means that all profiles are importable. */ + primary_metadata.num_entries = 0; } } R_END_TRY_CATCH; - /* Copy matching entries. */ + /* We want to return the set of profiles that can be imported, which is just the profiles we don't already have. */ u32 count = 0; for (u32 i = 0; i < arg.metadata.num_entries; ++i) { const auto &arg_entry = arg.metadata.entries[i]; + /* Check if we have the entry. */ + bool have_entry = false; for (u32 j = 0; j < primary_metadata.num_entries; ++j) { const auto &pri_entry = primary_metadata.entries[j]; if (pri_entry.identifier_0 == arg_entry.identifier_0 && pri_entry.identifier_1 == arg_entry.identifier_1) { - out[count++] = arg.entries[i]; + have_entry = true; break; } } + + /* If we don't already have the entry, it's importable -- copy it out. */ + if (!have_entry) { + out[count++] = arg.profile_urls[i]; + } } /* Set output count. */ diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp index d7508a250..8ebdac189 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp @@ -29,7 +29,7 @@ namespace ams::sprofile::srv { constexpr ServiceForBgAgent(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ } public: Result OpenProfileImporter(sf::Out> out); - Result GetMetadataEntryData(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg); + Result GetImportableProfileUrls(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg); Result IsUpdateNeeded(sf::Out out, Identifier revision_key); Result Reset(); }; diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp index 43c9e28f0..d20610a17 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp @@ -46,6 +46,10 @@ namespace ams::sprofile::srv { static_assert(util::is_pod::value); static_assert(sizeof(ProfileDataEntry) == 0x10); + static_assert(AMS_OFFSETOF(ProfileDataEntry, key) == 0x00); + static_assert(AMS_OFFSETOF(ProfileDataEntry, type) == 0x07); + static_assert(AMS_OFFSETOF(ProfileDataEntry, value_s64) == 0x08); + struct ProfileData { u32 num_entries; u8 unk_04[0x0C]; @@ -55,6 +59,11 @@ namespace ams::sprofile::srv { static_assert(util::is_pod::value); static_assert(sizeof(ProfileData) == 0x4000); + static_assert(AMS_OFFSETOF(ProfileData, num_entries) == 0x00); + static_assert(AMS_OFFSETOF(ProfileData, unk_04) == 0x04); + static_assert(AMS_OFFSETOF(ProfileData, unk_10) == 0x10); + static_assert(AMS_OFFSETOF(ProfileData, entries) == 0x30); + struct ServiceProfile { Identifier name; ProfileData data; @@ -62,6 +71,9 @@ namespace ams::sprofile::srv { static_assert(util::is_pod::value); static_assert(sizeof(ServiceProfile) == 0x4008); + static_assert(AMS_OFFSETOF(ServiceProfile, name) == 0x00); + static_assert(AMS_OFFSETOF(ServiceProfile, data) == 0x08); + struct ProfileDataForImportData : public sf::LargeData, public sf::PrefersMapAliasTransferMode { struct { Identifier identifier_0; @@ -77,6 +89,11 @@ namespace ams::sprofile::srv { static_assert(util::is_pod::value); static_assert(sizeof(ProfileDataForImportData) == 0x4400); + static_assert(AMS_OFFSETOF(ProfileDataForImportData, header) == 0x00); + static_assert(AMS_OFFSETOF(ProfileDataForImportData, hash) == 0x30); + static_assert(AMS_OFFSETOF(ProfileDataForImportData, data) == 0x40); + static_assert(AMS_OFFSETOF(ProfileDataForImportData, unk_4040) == 0x4040); + struct ProfileMetadataEntry { Identifier identifier_0; Identifier identifier_1; @@ -85,22 +102,34 @@ namespace ams::sprofile::srv { static_assert(util::is_pod::value); static_assert(sizeof(ProfileMetadataEntry) == 0x40); - struct ProfileMetadataEntryData : public sf::PrefersMapAliasTransferMode { - u8 unk[0x100]; + static_assert(AMS_OFFSETOF(ProfileMetadataEntry, identifier_0) == 0x00); + static_assert(AMS_OFFSETOF(ProfileMetadataEntry, identifier_1) == 0x07); + static_assert(AMS_OFFSETOF(ProfileMetadataEntry, unk_0E) == 0x0E); + + struct ProfileUrl : public sf::PrefersMapAliasTransferMode { + char url[0x100]; }; - static_assert(util::is_pod::value); - static_assert(sizeof(ProfileMetadataEntryData) == 0x100); + static_assert(util::is_pod::value); + static_assert(sizeof(ProfileUrl) == 0x100); struct ProfileMetadata { u32 num_entries; u32 unk_04; Identifier revision_key; + u8 unk_0F[0x1]; u8 unk_10[0x30]; ProfileMetadataEntry entries[50]; }; static_assert(util::is_pod::value); static_assert(sizeof(ProfileMetadata) == 0xCC0); + static_assert(AMS_OFFSETOF(ProfileMetadata, num_entries) == 0x00); + static_assert(AMS_OFFSETOF(ProfileMetadata, unk_04) == 0x04); + static_assert(AMS_OFFSETOF(ProfileMetadata, revision_key) == 0x08); + static_assert(AMS_OFFSETOF(ProfileMetadata, unk_0F) == 0x0F); + static_assert(AMS_OFFSETOF(ProfileMetadata, unk_10) == 0x10); + static_assert(AMS_OFFSETOF(ProfileMetadata, entries) == 0x40); + struct ProfileMetadataForImportMetadata : public sf::LargeData, public sf::PrefersMapAliasTransferMode { struct { u32 version; @@ -108,10 +137,16 @@ namespace ams::sprofile::srv { } header; u8 hash[crypto::Md5Generator::HashSize]; ProfileMetadata metadata; - ProfileMetadataEntryData entries[50]; - u8 unk[0x8000 - 0x3EF0]; + ProfileUrl profile_urls[50]; + u8 unk_3EF0[0x8000 - 0x3EF0]; }; static_assert(util::is_pod::value); static_assert(sizeof(ProfileMetadataForImportMetadata) == 0x8000); + static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, header) == 0x00); + static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, hash) == 0x20); + static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, metadata) == 0x30); + static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, profile_urls) == 0xCF0); + static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, unk_3EF0) == 0x3EF0); + }