diff --git a/SystemTools.cxx b/SystemTools.cxx index feeb65fc324b6cd3f831694727892d03e8226c8e..4fe388978e0cf2ea211a79a045343ce9aa25065e 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -3394,15 +3394,16 @@ static void SystemToolsAppendComponents( static const std::string cur = "."; for (std::vector<std::string>::const_iterator i = first; i != last; ++i) { if (*i == up) { - if (out_components.size() > 1) { + // Remove the previous component if possible. Ignore ../ components + // that try to go above the root. Keep ../ components if they are + // at the beginning of a relative path (base path is relative). + if (out_components.size() > 1 && out_components.back() != up) { out_components.resize(out_components.size() - 1); + } else if (!out_components.empty() && out_components[0].empty()) { + out_components.emplace_back(std::move(*i)); } } else if (!i->empty() && *i != cur) { -#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) - out_components.push_back(std::move(*i)); -#else - out_components.push_back(*i); -#endif + out_components.emplace_back(std::move(*i)); } } } diff --git a/testSystemTools.cxx b/testSystemTools.cxx index 9a40b53302e0869813d593d9223aa71438480f5e..ffa6a297d9fe7ece318af12b8302478b229d3abd 100644 --- a/testSystemTools.cxx +++ b/testSystemTools.cxx @@ -684,9 +684,10 @@ static bool CheckRelativePaths() } static bool CheckCollapsePath(const std::string& path, - const std::string& expected) + const std::string& expected, + const char* base = nullptr) { - std::string result = kwsys::SystemTools::CollapseFullPath(path); + std::string result = kwsys::SystemTools::CollapseFullPath(path, base); if (!kwsys::SystemTools::ComparePath(expected, result)) { std::cerr << "CollapseFullPath(" << path << ") yielded " << result << " instead of " << expected << std::endl; @@ -710,6 +711,9 @@ static bool CheckCollapsePath() res &= CheckCollapsePath("C:/", "C:/"); res &= CheckCollapsePath("C:/../", "C:/"); res &= CheckCollapsePath("C:/../../", "C:/"); + res &= CheckCollapsePath("../b", "../../b", "../"); + res &= CheckCollapsePath("../a/../b", "../b", "../rel"); + res &= CheckCollapsePath("a/../b", "../rel/b", "../rel"); return res; }