summaryrefslogtreecommitdiff
path: root/Source/Core/Common/NandPaths.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2016-11-29 18:34:22 +0100
committerGitHub <noreply@github.com>2016-11-29 18:34:22 +0100
commit3cfc49a613a0f8e137c251694c97f0f3589f3216 (patch)
tree158c4deb49e146888d1c1c0c8dd2252a7a8d7a01 /Source/Core/Common/NandPaths.cpp
parent97ebb02a07dcbaf9efaab3f084cb8cb917b53ef5 (diff)
parent0c6fd47460cb59c1b58c8870a4d2f05c23d8f357 (diff)
Merge pull request #4472 from JosJuice/revert-absolute-path
IOS HLE: Replace broken path traversal prevention
Diffstat (limited to 'Source/Core/Common/NandPaths.cpp')
-rw-r--r--Source/Core/Common/NandPaths.cpp75
1 files changed, 51 insertions, 24 deletions
diff --git a/Source/Core/Common/NandPaths.cpp b/Source/Core/Common/NandPaths.cpp
index 3dc554dce9..60cb49fa26 100644
--- a/Source/Core/Common/NandPaths.cpp
+++ b/Source/Core/Common/NandPaths.cpp
@@ -2,10 +2,12 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
+#include <algorithm>
#include <cstdio>
#include <fstream>
#include <stdlib.h>
#include <string>
+#include <unordered_set>
#include <utility>
#include "Common/CommonFuncs.h"
@@ -117,36 +119,61 @@ bool CheckTitleTIK(u64 _titleID, FromWhichRoot from)
return false;
}
-static void CreateReplacementFile(std::string& filename)
+std::string EscapeFileName(const std::string& filename)
{
- std::ofstream replace;
- OpenFStream(replace, filename, std::ios_base::out);
- replace << "\" __22__\n";
- replace << "* __2a__\n";
- // replace << "/ __2f__\n";
- replace << ": __3a__\n";
- replace << "< __3c__\n";
- replace << "> __3e__\n";
- replace << "? __3f__\n";
- // replace <<"\\ __5c__\n";
- replace << "| __7c__\n";
+ // Prevent paths from containing special names like ., .., ..., ...., and so on
+ if (std::all_of(filename.begin(), filename.end(), [](char c) { return c == '.'; }))
+ return ReplaceAll(filename, ".", "__2e__");
+
+ // Escape all double underscores since we will use double underscores for our escape sequences
+ std::string filename_with_escaped_double_underscores = ReplaceAll(filename, "__", "__5f____5f__");
+
+ // Escape all other characters that need to be escaped
+ static const std::unordered_set<char> chars_to_replace = {'\"', '*', '/', ':', '<',
+ '>', '?', '\\', '|', '\x7f'};
+ std::string result;
+ result.reserve(filename_with_escaped_double_underscores.size());
+ for (char c : filename_with_escaped_double_underscores)
+ {
+ if ((c >= 0 && c <= 0x1F) || chars_to_replace.find(c) != chars_to_replace.end())
+ result.append(StringFromFormat("__%02x__", c));
+ else
+ result.push_back(c);
+ }
+
+ return result;
+}
+
+std::string EscapePath(const std::string& path)
+{
+ std::vector<std::string> split_strings;
+ SplitString(path, '/', split_strings);
+
+ std::vector<std::string> escaped_split_strings;
+ escaped_split_strings.reserve(split_strings.size());
+ for (const std::string& split_string : split_strings)
+ escaped_split_strings.push_back(EscapeFileName(split_string));
+
+ return JoinStrings(escaped_split_strings, "/");
}
-void ReadReplacements(replace_v& replacements)
+std::string UnescapeFileName(const std::string& filename)
{
- replacements.clear();
- const std::string replace_fname = "/sys/replace";
- std::string filename = File::GetUserPath(D_SESSION_WIIROOT_IDX) + replace_fname;
+ std::string result = filename;
+ size_t pos = 0;
- if (!File::Exists(filename))
- CreateReplacementFile(filename);
+ // Replace escape sequences of the format "__3f__" with the ASCII
+ // character defined by the escape sequence's two hex digits.
+ while ((pos = result.find("__", pos)) != std::string::npos)
+ {
+ u32 character;
+ if (pos + 6 <= result.size() && result[pos + 4] == '_' && result[pos + 5] == '_')
+ if (AsciiToHex(result.substr(pos + 2, 2), character))
+ result.replace(pos, 6, {static_cast<char>(character)});
- std::ifstream f;
- OpenFStream(f, filename, std::ios_base::in);
- char letter;
- std::string replacement;
+ ++pos;
+ }
- while (f >> letter >> replacement && replacement.size())
- replacements.emplace_back(letter, replacement);
+ return result;
}
}