diff options
| author | 2018-10-04 12:23:18 -0400 | |
|---|---|---|
| committer | 2018-10-04 12:23:27 -0400 | |
| commit | 110d5784702282c594fe57f84f8d6bda21a82d50 (patch) | |
| tree | 4d4d2267784e1e0baa76dfb656b91503118f89b0 /src | |
| parent | ips_layer: Deduplicate resource usage (diff) | |
| download | yuzu-110d5784702282c594fe57f84f8d6bda21a82d50.tar.gz yuzu-110d5784702282c594fe57f84f8d6bda21a82d50.tar.xz yuzu-110d5784702282c594fe57f84f8d6bda21a82d50.zip | |
ips_layer: Fix inaccuracies with comments and flags
Specifically bugs/crashes that arise when putting them in positions that are legal but not typical, such as midline, between patch data, or between patch records.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/ips_layer.cpp | 64 | ||||
| -rw-r--r-- | src/core/file_sys/ips_layer.h | 1 | ||||
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 2 |
3 files changed, 51 insertions, 16 deletions
diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index abe3dcf62..0cadbc375 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp | |||
| @@ -123,6 +123,22 @@ static std::string EscapeStringSequences(std::string in) { | |||
| 123 | return in; | 123 | return in; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | void IPSwitchCompiler::ParseFlag(const std::string& line) { | ||
| 127 | if (StartsWith(line, "@flag offset_shift ")) { | ||
| 128 | // Offset Shift Flag | ||
| 129 | offset_shift = std::stoll(line.substr(19), nullptr, 0); | ||
| 130 | } else if (StartsWith(line, "@little-endian")) { | ||
| 131 | // Set values to read as little endian | ||
| 132 | is_little_endian = true; | ||
| 133 | } else if (StartsWith(line, "@big-endian")) { | ||
| 134 | // Set values to read as big endian | ||
| 135 | is_little_endian = false; | ||
| 136 | } else if (StartsWith(line, "@flag print_values")) { | ||
| 137 | // Force printing of applied values | ||
| 138 | print_values = true; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 126 | void IPSwitchCompiler::Parse() { | 142 | void IPSwitchCompiler::Parse() { |
| 127 | const auto bytes = patch_text->ReadAllBytes(); | 143 | const auto bytes = patch_text->ReadAllBytes(); |
| 128 | std::stringstream s; | 144 | std::stringstream s; |
| @@ -141,7 +157,17 @@ void IPSwitchCompiler::Parse() { | |||
| 141 | auto line = lines[i]; | 157 | auto line = lines[i]; |
| 142 | 158 | ||
| 143 | // Remove midline comments | 159 | // Remove midline comments |
| 144 | const auto comment_index = line.find("//"); | 160 | std::size_t comment_index = std::string::npos; |
| 161 | bool within_string = false; | ||
| 162 | for (std::size_t k = 0; k < line.size(); ++k) { | ||
| 163 | if (line[k] == '\"' && (k > 0 && line[k - 1] != '\\')) { | ||
| 164 | within_string = !within_string; | ||
| 165 | } else if (line[k] == '\\' && (k < line.size() - 1 && line[k + 1] == '\\')) { | ||
| 166 | comment_index = k; | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 145 | if (!StartsWith(line, "//") && comment_index != std::string::npos) { | 171 | if (!StartsWith(line, "//") && comment_index != std::string::npos) { |
| 146 | last_comment = line.substr(comment_index + 2); | 172 | last_comment = line.substr(comment_index + 2); |
| 147 | line = line.substr(0, comment_index); | 173 | line = line.substr(0, comment_index); |
| @@ -156,9 +182,6 @@ void IPSwitchCompiler::Parse() { | |||
| 156 | if (raw_build_id.size() != 0x40) | 182 | if (raw_build_id.size() != 0x40) |
| 157 | raw_build_id.resize(0x40, '0'); | 183 | raw_build_id.resize(0x40, '0'); |
| 158 | nso_build_id = Common::HexStringToArray<0x20>(raw_build_id); | 184 | nso_build_id = Common::HexStringToArray<0x20>(raw_build_id); |
| 159 | } else if (StartsWith(line, "@flag offset_shift ")) { | ||
| 160 | // Offset Shift Flag | ||
| 161 | offset_shift = std::stoll(line.substr(19), nullptr, 0); | ||
| 162 | } else if (StartsWith(line, "#")) { | 185 | } else if (StartsWith(line, "#")) { |
| 163 | // Mandatory Comment | 186 | // Mandatory Comment |
| 164 | LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Forced output comment: {}", | 187 | LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Forced output comment: {}", |
| @@ -170,15 +193,6 @@ void IPSwitchCompiler::Parse() { | |||
| 170 | continue; | 193 | continue; |
| 171 | if (last_comment.find_first_not_of(' ') != 0) | 194 | if (last_comment.find_first_not_of(' ') != 0) |
| 172 | last_comment = last_comment.substr(last_comment.find_first_not_of(' ')); | 195 | last_comment = last_comment.substr(last_comment.find_first_not_of(' ')); |
| 173 | } else if (StartsWith(line, "@little-endian")) { | ||
| 174 | // Set values to read as little endian | ||
| 175 | is_little_endian = true; | ||
| 176 | } else if (StartsWith(line, "@big-endian")) { | ||
| 177 | // Set values to read as big endian | ||
| 178 | is_little_endian = false; | ||
| 179 | } else if (StartsWith(line, "@flag print_values")) { | ||
| 180 | // Force printing of applied values | ||
| 181 | print_values = true; | ||
| 182 | } else if (StartsWith(line, "@enabled") || StartsWith(line, "@disabled")) { | 196 | } else if (StartsWith(line, "@enabled") || StartsWith(line, "@disabled")) { |
| 183 | // Start of patch | 197 | // Start of patch |
| 184 | const auto enabled = StartsWith(line, "@enabled"); | 198 | const auto enabled = StartsWith(line, "@enabled"); |
| @@ -195,6 +209,18 @@ void IPSwitchCompiler::Parse() { | |||
| 195 | break; | 209 | break; |
| 196 | const auto patch_line = lines[++i]; | 210 | const auto patch_line = lines[++i]; |
| 197 | 211 | ||
| 212 | // Start of new patch | ||
| 213 | if (StartsWith(patch_line, "@enabled") || StartsWith(patch_line, "@disabled")) { | ||
| 214 | --i; | ||
| 215 | break; | ||
| 216 | } | ||
| 217 | |||
| 218 | // Check for a flag | ||
| 219 | if (StartsWith(patch_line, "@")) { | ||
| 220 | ParseFlag(patch_line); | ||
| 221 | continue; | ||
| 222 | } | ||
| 223 | |||
| 198 | // 11 - 8 hex digit offset + space + minimum two digit overwrite val | 224 | // 11 - 8 hex digit offset + space + minimum two digit overwrite val |
| 199 | if (patch_line.length() < 11) | 225 | if (patch_line.length() < 11) |
| 200 | break; | 226 | break; |
| @@ -205,9 +231,15 @@ void IPSwitchCompiler::Parse() { | |||
| 205 | // 9 - first char of replacement val | 231 | // 9 - first char of replacement val |
| 206 | if (patch_line[9] == '\"') { | 232 | if (patch_line[9] == '\"') { |
| 207 | // string replacement | 233 | // string replacement |
| 208 | const auto end_index = patch_line.find('\"', 10); | 234 | auto end_index = patch_line.find('\"', 10); |
| 209 | if (end_index == std::string::npos || end_index < 10) | 235 | if (end_index == std::string::npos || end_index < 10) |
| 210 | return; | 236 | return; |
| 237 | while (patch_line[end_index - 1] == '\\') { | ||
| 238 | end_index = patch_line.find('\"', end_index + 1); | ||
| 239 | if (end_index == std::string::npos || end_index < 10) | ||
| 240 | return; | ||
| 241 | } | ||
| 242 | |||
| 211 | auto value = patch_line.substr(10, end_index - 10); | 243 | auto value = patch_line.substr(10, end_index - 10); |
| 212 | value = EscapeStringSequences(value); | 244 | value = EscapeStringSequences(value); |
| 213 | replace.reserve(value.size()); | 245 | replace.reserve(value.size()); |
| @@ -226,10 +258,12 @@ void IPSwitchCompiler::Parse() { | |||
| 226 | patch_text->GetName(), offset, Common::HexVectorToString(replace)); | 258 | patch_text->GetName(), offset, Common::HexVectorToString(replace)); |
| 227 | } | 259 | } |
| 228 | 260 | ||
| 229 | patch.records.emplace(offset, std::move(replace)); | 261 | patch.records.insert_or_assign(offset, std::move(replace)); |
| 230 | } | 262 | } |
| 231 | 263 | ||
| 232 | patches.push_back(std::move(patch)); | 264 | patches.push_back(std::move(patch)); |
| 265 | } else if (StartsWith(line, "@")) { | ||
| 266 | ParseFlag(line); | ||
| 233 | } | 267 | } |
| 234 | } | 268 | } |
| 235 | 269 | ||
diff --git a/src/core/file_sys/ips_layer.h b/src/core/file_sys/ips_layer.h index b07cc5673..57da00da8 100644 --- a/src/core/file_sys/ips_layer.h +++ b/src/core/file_sys/ips_layer.h | |||
| @@ -22,6 +22,7 @@ public: | |||
| 22 | VirtualFile Apply(const VirtualFile& in) const; | 22 | VirtualFile Apply(const VirtualFile& in) const; |
| 23 | 23 | ||
| 24 | private: | 24 | private: |
| 25 | void ParseFlag(const std::string& flag); | ||
| 25 | void Parse(); | 26 | void Parse(); |
| 26 | 27 | ||
| 27 | bool valid = false; | 28 | bool valid = false; |
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 03df24906..ab2e5e43d 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -76,7 +76,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 76 | static std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs, | 76 | static std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs, |
| 77 | const std::string& build_id) { | 77 | const std::string& build_id) { |
| 78 | std::vector<VirtualFile> out; | 78 | std::vector<VirtualFile> out; |
| 79 | ips.reserve(patch_dirs.size()); | 79 | out.reserve(patch_dirs.size()); |
| 80 | for (const auto& subdir : patch_dirs) { | 80 | for (const auto& subdir : patch_dirs) { |
| 81 | auto exefs_dir = subdir->GetSubdirectory("exefs"); | 81 | auto exefs_dir = subdir->GetSubdirectory("exefs"); |
| 82 | if (exefs_dir != nullptr) { | 82 | if (exefs_dir != nullptr) { |