Merge pull request #6142 from lat9nq/prog_meta_ref_bind_address
program_metadata: Avoid reference binding to misaligned address
This commit is contained in:
		| @@ -33,11 +33,55 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) { | ||||
|         return Loader::ResultStatus::ErrorBadACIHeader; | ||||
|     } | ||||
|  | ||||
|     if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) { | ||||
|     // Load acid_file_access per-component instead of the entire struct, since this struct does not | ||||
|     // reflect the layout of the real data. | ||||
|     std::size_t current_offset = acid_header.fac_offset; | ||||
|     if (sizeof(FileAccessControl::version) != file->ReadBytes(&acid_file_access.version, | ||||
|                                                               sizeof(FileAccessControl::version), | ||||
|                                                               current_offset)) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessControl; | ||||
|     } | ||||
|     if (sizeof(FileAccessControl::permissions) != | ||||
|         file->ReadBytes(&acid_file_access.permissions, sizeof(FileAccessControl::permissions), | ||||
|                         current_offset += sizeof(FileAccessControl::version) + 3)) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessControl; | ||||
|     } | ||||
|     if (sizeof(FileAccessControl::unknown) != | ||||
|         file->ReadBytes(&acid_file_access.unknown, sizeof(FileAccessControl::unknown), | ||||
|                         current_offset + sizeof(FileAccessControl::permissions))) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessControl; | ||||
|     } | ||||
|  | ||||
|     if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) { | ||||
|     // Load aci_file_access per-component instead of the entire struct, same as acid_file_access | ||||
|     current_offset = aci_header.fah_offset; | ||||
|     if (sizeof(FileAccessHeader::version) != file->ReadBytes(&aci_file_access.version, | ||||
|                                                              sizeof(FileAccessHeader::version), | ||||
|                                                              current_offset)) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||||
|     } | ||||
|     if (sizeof(FileAccessHeader::permissions) != | ||||
|         file->ReadBytes(&aci_file_access.permissions, sizeof(FileAccessHeader::permissions), | ||||
|                         current_offset += sizeof(FileAccessHeader::version) + 3)) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||||
|     } | ||||
|     if (sizeof(FileAccessHeader::unk_offset) != | ||||
|         file->ReadBytes(&aci_file_access.unk_offset, sizeof(FileAccessHeader::unk_offset), | ||||
|                         current_offset += sizeof(FileAccessHeader::permissions))) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||||
|     } | ||||
|     if (sizeof(FileAccessHeader::unk_size) != | ||||
|         file->ReadBytes(&aci_file_access.unk_size, sizeof(FileAccessHeader::unk_size), | ||||
|                         current_offset += sizeof(FileAccessHeader::unk_offset))) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||||
|     } | ||||
|     if (sizeof(FileAccessHeader::unk_offset_2) != | ||||
|         file->ReadBytes(&aci_file_access.unk_offset_2, sizeof(FileAccessHeader::unk_offset_2), | ||||
|                         current_offset += sizeof(FileAccessHeader::unk_size))) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||||
|     } | ||||
|     if (sizeof(FileAccessHeader::unk_size_2) != | ||||
|         file->ReadBytes(&aci_file_access.unk_size_2, sizeof(FileAccessHeader::unk_size_2), | ||||
|                         current_offset + sizeof(FileAccessHeader::unk_offset_2))) { | ||||
|         return Loader::ResultStatus::ErrorBadFileAccessHeader; | ||||
|     } | ||||
|  | ||||
| @@ -152,9 +196,7 @@ void ProgramMetadata::Print() const { | ||||
|     LOG_DEBUG(Service_FS, " > Is Retail:           {}", acid_header.is_retail ? "YES" : "NO"); | ||||
|     LOG_DEBUG(Service_FS, "Title ID Min:           0x{:016X}", acid_header.title_id_min); | ||||
|     LOG_DEBUG(Service_FS, "Title ID Max:           0x{:016X}", acid_header.title_id_max); | ||||
|     u64_le permissions_l; // local copy to fix alignment error | ||||
|     std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l)); | ||||
|     LOG_DEBUG(Service_FS, "Filesystem Access:      0x{:016X}\n", permissions_l); | ||||
|     LOG_DEBUG(Service_FS, "Filesystem Access:      0x{:016X}\n", acid_file_access.permissions); | ||||
|  | ||||
|     // Begin ACI0 printing (actual perms, unsigned) | ||||
|     LOG_DEBUG(Service_FS, "Magic:                  {:.4}", aci_header.magic.data()); | ||||
|   | ||||
| @@ -144,20 +144,18 @@ private: | ||||
|  | ||||
|     static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong"); | ||||
|  | ||||
| #pragma pack(push, 1) | ||||
|  | ||||
|     // FileAccessControl and FileAccessHeader need loaded per-component: this layout does not | ||||
|     // reflect the real layout to avoid reference binding to misaligned addresses | ||||
|     struct FileAccessControl { | ||||
|         u8 version; | ||||
|         INSERT_PADDING_BYTES(3); | ||||
|         // 3 padding bytes | ||||
|         u64_le permissions; | ||||
|         std::array<u8, 0x20> unknown; | ||||
|     }; | ||||
|  | ||||
|     static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong"); | ||||
|  | ||||
|     struct FileAccessHeader { | ||||
|         u8 version; | ||||
|         INSERT_PADDING_BYTES(3); | ||||
|         // 3 padding bytes | ||||
|         u64_le permissions; | ||||
|         u32_le unk_offset; | ||||
|         u32_le unk_size; | ||||
| @@ -165,10 +163,6 @@ private: | ||||
|         u32_le unk_size_2; | ||||
|     }; | ||||
|  | ||||
|     static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong"); | ||||
|  | ||||
| #pragma pack(pop) | ||||
|  | ||||
|     Header npdm_header; | ||||
|     AciHeader aci_header; | ||||
|     AcidHeader acid_header; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user