diff options
author | Nico Weber <thakis@chromium.org> | 2020-05-03 12:46:46 -0400 |
---|---|---|
committer | Nico Weber <thakis@chromium.org> | 2020-05-03 12:46:46 -0400 |
commit | fb5fd74685e728b1d5e68d33e9842bcd734b98e6 (patch) | |
tree | 21c5186b0ff430fc154528e29aa3cd88d0193db0 /llvm/lib/Support/Path.cpp | |
parent | ff5094c03f7d4c126c8e052a63c7255572200adb (diff) | |
download | llvm-fb5fd74685e728b1d5e68d33e9842bcd734b98e6.zip llvm-fb5fd74685e728b1d5e68d33e9842bcd734b98e6.tar.gz llvm-fb5fd74685e728b1d5e68d33e9842bcd734b98e6.tar.bz2 |
Revert "Optimize path::remove_dots"
This reverts commit 53913a65b408ade2956061b4c0aaed6bba907403.
Breaks VFSFromYAMLTest.DirectoryIterationSameDirMultipleEntries
in SupportTests on non-Windows.
Diffstat (limited to 'llvm/lib/Support/Path.cpp')
-rw-r--r-- | llvm/lib/Support/Path.cpp | 77 |
1 files changed, 27 insertions, 50 deletions
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp index f5ab250..6f065b9c 100644 --- a/llvm/lib/Support/Path.cpp +++ b/llvm/lib/Support/Path.cpp @@ -684,66 +684,43 @@ StringRef remove_leading_dotslash(StringRef Path, Style style) { return Path; } -// Remove path traversal components ("." and "..") when possible, and -// canonicalize slashes. -bool remove_dots(SmallVectorImpl<char> &the_path, bool remove_dot_dot, - Style style) { - style = real_style(style); - StringRef remaining(the_path.data(), the_path.size()); - bool needs_change = false; +static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot, + Style style) { SmallVector<StringRef, 16> components; - // Consume the root path, if present. - StringRef root = path::root_path(remaining, style); - bool absolute = !root.empty(); - if (absolute) - remaining = remaining.drop_front(root.size()); - - // Loop over path components manually. This makes it easier to detect - // non-preferred slashes and double separators that must be canonicalized. - while (!remaining.empty()) { - size_t next_slash = remaining.find_first_of(separators(style)); - if (next_slash == StringRef::npos) - next_slash = remaining.size(); - StringRef component = remaining.take_front(next_slash); - remaining = remaining.drop_front(next_slash); - - // Eat the slash, and check if it is the preferred separator. - if (!remaining.empty()) { - needs_change |= remaining.front() != preferred_separator(style); - remaining = remaining.drop_front(); - } - - // Check for path traversal components or double separators. - if (component.empty() || component == ".") { - needs_change = true; - } else if (remove_dot_dot && component == "..") { - needs_change = true; - // Do not allow ".." to remove the root component. If this is the - // beginning of a relative path, keep the ".." component. + // Skip the root path, then look for traversal in the components. + StringRef rel = path::relative_path(path, style); + for (StringRef C : + llvm::make_range(path::begin(rel, style), path::end(rel))) { + if (C == ".") + continue; + // Leading ".." will remain in the path unless it's at the root. + if (remove_dot_dot && C == "..") { if (!components.empty() && components.back() != "..") { components.pop_back(); - } else if (!absolute) { - components.push_back(component); + continue; } - } else { - components.push_back(component); + if (path::is_absolute(path, style)) + continue; } + components.push_back(C); } - // Avoid rewriting the path unless we have to. - if (!needs_change) + SmallString<256> buffer = path::root_path(path, style); + for (StringRef C : components) + path::append(buffer, style, C); + return buffer; +} + +bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot, + Style style) { + StringRef p(path.data(), path.size()); + + SmallString<256> result = remove_dots(p, remove_dot_dot, style); + if (result == path) return false; - SmallString<256> buffer = root; - if (!components.empty()) { - buffer += components[0]; - for (StringRef C : makeArrayRef(components).drop_front()) { - buffer += preferred_separator(style); - buffer += C; - } - } - the_path.swap(buffer); + path.swap(result); return true; } |