summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@serenityos.org>2020-05-22 20:50:01 +0300
committerAndreas Kling <kling@serenityos.org>2020-05-22 23:55:35 +0200
commita3e4dfdf9859a9b955bf4728328f740a47de5851 (patch)
tree408582feb0f96ede21df0126b4c8e572d6b0e247 /AK
parent75f587d3dffd268a21aa5f24e462642b99f4fd44 (diff)
downloadserenity-a3e4dfdf9859a9b955bf4728328f740a47de5851.zip
AK: Fix .. handling in FileSystemPath
We shouldn't just drop leading ..-s for relative paths. At the same time, we should handle paths like ../foo/../../bar correctly: the first .. after the foo cancels out the foo, but the second one should get treated as a leading one and not get dropped. Note that since this path resolution is purely lexical, it's never going to be completely correct with respect to symlinks and other filesystem magic. Better don't use it when dealing with files.
Diffstat (limited to 'AK')
-rw-r--r--AK/FileSystemPath.cpp24
1 files changed, 14 insertions, 10 deletions
diff --git a/AK/FileSystemPath.cpp b/AK/FileSystemPath.cpp
index ef0e824d7b..21bb5fd3b3 100644
--- a/AK/FileSystemPath.cpp
+++ b/AK/FileSystemPath.cpp
@@ -48,22 +48,26 @@ void FileSystemPath::canonicalize()
m_is_absolute = m_string[0] == '/';
auto parts = m_string.split_view('/');
- if (!m_is_absolute)
- parts.prepend(".");
-
size_t approximate_canonical_length = 0;
Vector<String> canonical_parts;
for (size_t i = 0; i < parts.size(); ++i) {
auto& part = parts[i];
- if (m_is_absolute || i != 0) {
- if (part == ".")
- continue;
- }
- if (part == "..") {
- if (!canonical_parts.is_empty())
- canonical_parts.take_last();
+ if (part == ".")
continue;
+ if (part == "..") {
+ if (canonical_parts.is_empty()) {
+ if (m_is_absolute) {
+ // At the root, .. does nothing.
+ continue;
+ }
+ } else {
+ if (canonical_parts.last() != "..") {
+ // A .. and a previous non-.. part cancel each other.
+ canonical_parts.take_last();
+ continue;
+ }
+ }
}
if (!part.is_empty()) {
approximate_canonical_length += part.length() + 1;