summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2022-10-06 20:42:15 -0700
committerGravatar GitHub2022-10-06 20:42:15 -0700
commit61883d8820c057259c6c6113934a44f69742164c (patch)
treeeaae02f36b56101035ec9f79fc008ec0e2d2a938 /src
parentMerge pull request #8944 from Tachi107/patch-2 (diff)
parentprogram_metadata: Unpack FileAccessHeader and FileAccessControl (diff)
downloadyuzu-61883d8820c057259c6c6113934a44f69742164c.tar.gz
yuzu-61883d8820c057259c6c6113934a44f69742164c.tar.xz
yuzu-61883d8820c057259c6c6113934a44f69742164c.zip
Merge pull request #6142 from lat9nq/prog_meta_ref_bind_address
program_metadata: Avoid reference binding to misaligned address
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/program_metadata.cpp52
-rw-r--r--src/core/file_sys/program_metadata.h14
2 files changed, 51 insertions, 15 deletions
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index e0cdf3520..08d489eab 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -33,11 +33,55 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
33 return Loader::ResultStatus::ErrorBadACIHeader; 33 return Loader::ResultStatus::ErrorBadACIHeader;
34 } 34 }
35 35
36 if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) { 36 // Load acid_file_access per-component instead of the entire struct, since this struct does not
37 // reflect the layout of the real data.
38 std::size_t current_offset = acid_header.fac_offset;
39 if (sizeof(FileAccessControl::version) != file->ReadBytes(&acid_file_access.version,
40 sizeof(FileAccessControl::version),
41 current_offset)) {
42 return Loader::ResultStatus::ErrorBadFileAccessControl;
43 }
44 if (sizeof(FileAccessControl::permissions) !=
45 file->ReadBytes(&acid_file_access.permissions, sizeof(FileAccessControl::permissions),
46 current_offset += sizeof(FileAccessControl::version) + 3)) {
47 return Loader::ResultStatus::ErrorBadFileAccessControl;
48 }
49 if (sizeof(FileAccessControl::unknown) !=
50 file->ReadBytes(&acid_file_access.unknown, sizeof(FileAccessControl::unknown),
51 current_offset + sizeof(FileAccessControl::permissions))) {
37 return Loader::ResultStatus::ErrorBadFileAccessControl; 52 return Loader::ResultStatus::ErrorBadFileAccessControl;
38 } 53 }
39 54
40 if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) { 55 // Load aci_file_access per-component instead of the entire struct, same as acid_file_access
56 current_offset = aci_header.fah_offset;
57 if (sizeof(FileAccessHeader::version) != file->ReadBytes(&aci_file_access.version,
58 sizeof(FileAccessHeader::version),
59 current_offset)) {
60 return Loader::ResultStatus::ErrorBadFileAccessHeader;
61 }
62 if (sizeof(FileAccessHeader::permissions) !=
63 file->ReadBytes(&aci_file_access.permissions, sizeof(FileAccessHeader::permissions),
64 current_offset += sizeof(FileAccessHeader::version) + 3)) {
65 return Loader::ResultStatus::ErrorBadFileAccessHeader;
66 }
67 if (sizeof(FileAccessHeader::unk_offset) !=
68 file->ReadBytes(&aci_file_access.unk_offset, sizeof(FileAccessHeader::unk_offset),
69 current_offset += sizeof(FileAccessHeader::permissions))) {
70 return Loader::ResultStatus::ErrorBadFileAccessHeader;
71 }
72 if (sizeof(FileAccessHeader::unk_size) !=
73 file->ReadBytes(&aci_file_access.unk_size, sizeof(FileAccessHeader::unk_size),
74 current_offset += sizeof(FileAccessHeader::unk_offset))) {
75 return Loader::ResultStatus::ErrorBadFileAccessHeader;
76 }
77 if (sizeof(FileAccessHeader::unk_offset_2) !=
78 file->ReadBytes(&aci_file_access.unk_offset_2, sizeof(FileAccessHeader::unk_offset_2),
79 current_offset += sizeof(FileAccessHeader::unk_size))) {
80 return Loader::ResultStatus::ErrorBadFileAccessHeader;
81 }
82 if (sizeof(FileAccessHeader::unk_size_2) !=
83 file->ReadBytes(&aci_file_access.unk_size_2, sizeof(FileAccessHeader::unk_size_2),
84 current_offset + sizeof(FileAccessHeader::unk_offset_2))) {
41 return Loader::ResultStatus::ErrorBadFileAccessHeader; 85 return Loader::ResultStatus::ErrorBadFileAccessHeader;
42 } 86 }
43 87
@@ -152,9 +196,7 @@ void ProgramMetadata::Print() const {
152 LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO"); 196 LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
153 LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min); 197 LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
154 LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max); 198 LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
155 u64_le permissions_l; // local copy to fix alignment error 199 LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);
156 std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l));
157 LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", permissions_l);
158 200
159 // Begin ACI0 printing (actual perms, unsigned) 201 // Begin ACI0 printing (actual perms, unsigned)
160 LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data()); 202 LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index e8fb4e27f..2e8960b07 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -144,20 +144,18 @@ private:
144 144
145 static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong"); 145 static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong");
146 146
147#pragma pack(push, 1) 147 // FileAccessControl and FileAccessHeader need loaded per-component: this layout does not
148 148 // reflect the real layout to avoid reference binding to misaligned addresses
149 struct FileAccessControl { 149 struct FileAccessControl {
150 u8 version; 150 u8 version;
151 INSERT_PADDING_BYTES(3); 151 // 3 padding bytes
152 u64_le permissions; 152 u64_le permissions;
153 std::array<u8, 0x20> unknown; 153 std::array<u8, 0x20> unknown;
154 }; 154 };
155 155
156 static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong");
157
158 struct FileAccessHeader { 156 struct FileAccessHeader {
159 u8 version; 157 u8 version;
160 INSERT_PADDING_BYTES(3); 158 // 3 padding bytes
161 u64_le permissions; 159 u64_le permissions;
162 u32_le unk_offset; 160 u32_le unk_offset;
163 u32_le unk_size; 161 u32_le unk_size;
@@ -165,10 +163,6 @@ private:
165 u32_le unk_size_2; 163 u32_le unk_size_2;
166 }; 164 };
167 165
168 static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong");
169
170#pragma pack(pop)
171
172 Header npdm_header; 166 Header npdm_header;
173 AciHeader aci_header; 167 AciHeader aci_header;
174 AcidHeader acid_header; 168 AcidHeader acid_header;