mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	savestates: validate states before load
This commit is contained in:
		
							parent
							
								
									8e8c8fa37a
								
							
						
					
					
						commit
						c79acdd88d
					
				
					 1 changed files with 38 additions and 16 deletions
				
			
		|  | @ -49,6 +49,30 @@ std::string GetSaveStatePath(u64 program_id, u32 slot) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64 program_id, | ||||
|                               u32 slot) { | ||||
|     const auto path = GetSaveStatePath(program_id, slot); | ||||
|     if (header.filetype != header_magic_bytes) { | ||||
|         LOG_WARNING(Core, "Invalid save state file {}", path); | ||||
|         return false; | ||||
|     } | ||||
|     info.time = header.time; | ||||
| 
 | ||||
|     if (header.program_id != program_id) { | ||||
|         LOG_WARNING(Core, "Save state file isn't for the current game {}", path); | ||||
|         return false; | ||||
|     } | ||||
|     const std::string revision = fmt::format("{:02x}", fmt::join(header.revision, "")); | ||||
|     if (revision == Common::g_scm_rev) { | ||||
|         info.status = SaveStateInfo::ValidationStatus::OK; | ||||
|     } else { | ||||
|         LOG_WARNING(Core, "Save state file {} created from a different revision {}", path, | ||||
|                     revision); | ||||
|         info.status = SaveStateInfo::ValidationStatus::RevisionDismatch; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| std::vector<SaveStateInfo> ListSaveStates(u64 program_id) { | ||||
|     std::vector<SaveStateInfo> result; | ||||
|     for (u32 slot = 1; slot <= SaveStateSlotCount; ++slot) { | ||||
|  | @ -74,24 +98,10 @@ std::vector<SaveStateInfo> ListSaveStates(u64 program_id) { | |||
|             LOG_ERROR(Core, "Could not read from file {}", path); | ||||
|             continue; | ||||
|         } | ||||
|         if (header.filetype != header_magic_bytes) { | ||||
|             LOG_WARNING(Core, "Invalid save state file {}", path); | ||||
|         if (!ValidateSaveState(header, info, program_id, slot)) { | ||||
|             continue; | ||||
|         } | ||||
|         info.time = header.time; | ||||
| 
 | ||||
|         if (header.program_id != program_id) { | ||||
|             LOG_WARNING(Core, "Save state file isn't for the current game {}", path); | ||||
|             continue; | ||||
|         } | ||||
|         const std::string revision = fmt::format("{:02x}", fmt::join(header.revision, "")); | ||||
|         if (revision == Common::g_scm_rev) { | ||||
|             info.status = SaveStateInfo::ValidationStatus::OK; | ||||
|         } else { | ||||
|             LOG_WARNING(Core, "Save state file {} created from a different revision {}", path, | ||||
|                         revision); | ||||
|             info.status = SaveStateInfo::ValidationStatus::RevisionDismatch; | ||||
|         } | ||||
|         result.emplace_back(std::move(info)); | ||||
|     } | ||||
|     return result; | ||||
|  | @ -146,7 +156,19 @@ void System::LoadState(u32 slot) { | |||
|         std::vector<u8> buffer(FileUtil::GetSize(path) - sizeof(CSTHeader)); | ||||
| 
 | ||||
|         FileUtil::IOFile file(path, "rb"); | ||||
|         file.Seek(sizeof(CSTHeader), SEEK_SET); // Skip header
 | ||||
| 
 | ||||
|         // load header
 | ||||
|         CSTHeader header; | ||||
|         if (file.ReadBytes(&header, sizeof(header)) != sizeof(header)) { | ||||
|             throw std::runtime_error("Could not read from file at " + path); | ||||
|         } | ||||
| 
 | ||||
|         // validate header
 | ||||
|         SaveStateInfo info; | ||||
|         if (!ValidateSaveState(header, info, title_id, slot)) { | ||||
|             throw std::runtime_error("Invalid savestate"); | ||||
|         } | ||||
| 
 | ||||
|         if (file.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) { | ||||
|             throw std::runtime_error("Could not read from file at " + path); | ||||
|         } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue