Make sure that cd to a relative CDPATH results in absolute $PWD

We have had multiple crashes for relative CDPATH entries.  Commit 5e274066e
(Always return absolute path in path_get_cdpath, 2019-10-17) tried to fix
all of them but it failed to do justice to its title.  Let's fix this to
actually return absolute paths, always.  Take care to to normalize the path
because it is used for autosuggestions. The normalization is mostly relevant
for CDPATH=. (the default) but it doesn't hurt others.

Closes #9407
This commit is contained in:
Johannes Altmanninger 2022-12-10 10:56:17 +01:00
parent b0ec7e07b8
commit 892a820672
2 changed files with 19 additions and 14 deletions

View file

@ -186,24 +186,20 @@ wcstring_list_t path_apply_cdpath(const wcstring &dir, const wcstring &wd,
}
// Always append $PWD
cdpathsv.push_back(L".");
for (wcstring next_path : cdpathsv) {
if (next_path.empty()) next_path = L".";
if (next_path == L".") {
// next_path is just '.', and we have a working directory, so use the wd instead.
next_path = wd;
}
for (const wcstring &path : cdpathsv) {
wcstring abspath;
// We want to return an absolute path (see issue 6220)
if (string_prefixes_string(L"./", next_path)) {
next_path = next_path.replace(0, 2, wd);
} else if (string_prefixes_string(L"../", next_path) || next_path == L"..") {
next_path = next_path.insert(0, wd);
if (path.empty() || (path.front() != L'/' && path.front() != L'~')) {
abspath = wd;
abspath += L'/';
}
abspath += path;
expand_tilde(next_path, env_vars);
if (next_path.empty()) continue;
expand_tilde(abspath, env_vars);
if (abspath.empty()) continue;
abspath = normalize_path(abspath);
wcstring whole_path = std::move(next_path);
wcstring whole_path = std::move(abspath);
append_path_component(whole_path, dir);
paths.push_back(whole_path);
}

View file

@ -258,3 +258,12 @@ end
# CHECKERR: ^
# CHECKERR: in function 'cd' with arguments 'broken-symbolic-link'
# CHECKERR: called on line {{\d+}} of file {{.*}}/cd.fish
begin
mkdir -p foo/bar/muf
set -lx CDPATH foo/bar
cd muf
echo $PWD | grep -q ^/ && echo '$PWD is absolute'
# CHECK: $PWD is absolute
cd ../../..
end