sprofile: fix off-by-one in struct definition, fix GetImportableProfileUrls

This commit is contained in:
Michael Scire 2021-10-29 15:41:25 -07:00
parent d1f3c4904b
commit 2a0b99d9f9
5 changed files with 59 additions and 18 deletions

View file

@ -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<sf::SharedPointer<::ams::sprofile::IProfileImporter>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 200, Result, GetMetadataEntryData, (sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileMetadataEntryData> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \
AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out<bool> 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<sf::SharedPointer<::ams::sprofile::IProfileImporter>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 200, Result, GetImportableProfileUrls, (sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \
AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out<bool> 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)

View file

@ -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<size_t>(import.metadata.num_entries, util::size(import.metadata.entries)));
md5.Update(std::addressof(import.profile_urls), sizeof(import.profile_urls[0]) * std::min<size_t>(import.metadata.num_entries, util::size(import.metadata.entries)));
u8 hash[crypto::Md5Generator::HashSize];
md5.GetHash(hash, sizeof(hash));

View file

@ -34,7 +34,7 @@ namespace ams::sprofile::srv {
return ResultSuccess();
}
Result ServiceForBgAgent::GetMetadataEntryData(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileMetadataEntryData> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg) {
Result ServiceForBgAgent::GetImportableProfileUrls(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &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. */

View file

@ -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<sf::SharedPointer<::ams::sprofile::IProfileImporter>> out);
Result GetMetadataEntryData(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileMetadataEntryData> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg);
Result GetImportableProfileUrls(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg);
Result IsUpdateNeeded(sf::Out<bool> out, Identifier revision_key);
Result Reset();
};

View file

@ -46,6 +46,10 @@ namespace ams::sprofile::srv {
static_assert(util::is_pod<ProfileDataEntry>::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<ProfileData>::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<ServiceProfile>::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<ProfileDataForImportData>::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<ProfileMetadataEntry>::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<ProfileMetadataEntryData>::value);
static_assert(sizeof(ProfileMetadataEntryData) == 0x100);
static_assert(util::is_pod<ProfileUrl>::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<ProfileMetadata>::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<ProfileMetadataForImportMetadata>::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);
}