diff options
| author | 2022-10-06 20:42:15 -0700 | |
|---|---|---|
| committer | 2022-10-06 20:42:15 -0700 | |
| commit | 61883d8820c057259c6c6113934a44f69742164c (patch) | |
| tree | eaae02f36b56101035ec9f79fc008ec0e2d2a938 /src | |
| parent | Merge pull request #8944 from Tachi107/patch-2 (diff) | |
| parent | program_metadata: Unpack FileAccessHeader and FileAccessControl (diff) | |
| download | yuzu-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.cpp | 52 | ||||
| -rw-r--r-- | src/core/file_sys/program_metadata.h | 14 |
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; |