From 892a8206727961c2c6c597bd19f4d35d58164ce5 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sat, 10 Dec 2022 10:56:17 +0100 Subject: [PATCH] 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 --- src/path.cpp | 24 ++++++++++-------------- tests/checks/cd.fish | 9 +++++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/path.cpp b/src/path.cpp index 40dffcf79..3a5f9772b 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -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); } diff --git a/tests/checks/cd.fish b/tests/checks/cd.fish index 7618d9bcd..3ef82c0fa 100644 --- a/tests/checks/cd.fish +++ b/tests/checks/cd.fish @@ -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