From: Joel Rosdahl Date: Tue, 9 Sep 2025 16:34:34 +0000 (+0200) Subject: fix: Avoid expanding symlinks in relative path candidates X-Git-Tag: v4.12~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8810fadab0b59c03cff4c4dc24b00c571a0786ba;p=thirdparty%2Fccache.git fix: Avoid expanding symlinks in relative path candidates Commit 8223ed38abd9cf75ab75cb19dc2081c44bf568d0 changed make_relative_path to also try matching real_path(path) against the apparent/actual CWD, assuming that an absolute path p could be substituted with real_path(p). This assumption is incorrect for source files: if the source file includes a file via a relative path, expanding symlinks may cause the include file to be searched in the wrong directory. Fix by reverting that change. The new test case "Symlink to source file, longer symlink path" fails without this fix. Note: this effectively reverts #724. Fixes #1620. --- diff --git a/src/ccache/util/path.cpp b/src/ccache/util/path.cpp index 4f58eb79..855dc587 100644 --- a/src/ccache/util/path.cpp +++ b/src/ccache/util/path.cpp @@ -91,18 +91,11 @@ make_relative_path(const fs::path& actual_cwd, closest_existing_path = closest_existing_path.parent_path(); } - const auto add_relpath_candidates = [&](auto p) { - relpath_candidates.push_back(p.lexically_relative(actual_cwd)); - if (apparent_cwd != actual_cwd) { - relpath_candidates.emplace_back(p.lexically_relative(apparent_cwd)); - } - }; - - add_relpath_candidates(closest_existing_path); - const fs::path real_closest_existing_path = - fs::canonical(closest_existing_path).value_or(closest_existing_path); - if (real_closest_existing_path != closest_existing_path) { - add_relpath_candidates(real_closest_existing_path); + relpath_candidates.push_back( + closest_existing_path.lexically_relative(actual_cwd)); + if (apparent_cwd != actual_cwd) { + relpath_candidates.emplace_back( + closest_existing_path.lexically_relative(apparent_cwd)); } // Find best (i.e. shortest existing) match: diff --git a/test/suites/basedir.bash b/test/suites/basedir.bash index 9f237422..122e1c66 100644 --- a/test/suites/basedir.bash +++ b/test/suites/basedir.bash @@ -117,7 +117,7 @@ fi # ------------------------------------------------------------------------- if ! $HOST_OS_WINDOWS && ! $HOST_OS_CYGWIN; then - TEST "Symlink to source file" + TEST "Symlink to source file, shorter symlink path" mkdir dir cd dir @@ -138,6 +138,29 @@ EOF fi fi + # ------------------------------------------------------------------------- +if ! $HOST_OS_WINDOWS && ! $HOST_OS_CYGWIN; then + TEST "Symlink to source file, longer symlink path" + + mkdir dir + cd dir + mkdir d + echo '#define A "BUG"' >h.h + cat <c.c +#include +#include "h.h" +int main() { printf("%s\n", A); } +EOF + echo '#define A "OK"' >d/h.h + ln -s ../c.c d/c.c + + CCACHE_BASEDIR=/ $CCACHE_COMPILE -c $PWD/d/c.c + $COMPILER c.o -o c + if [ "$(./c)" != OK ]; then + test_failed "Incorrect header file used" + fi +fi + # ------------------------------------------------------------------------- if ! $HOST_OS_WINDOWS && ! $HOST_OS_CYGWIN; then TEST "Symlinked build dir inside source dir" @@ -411,13 +434,13 @@ fi TEST "Relative PWD" cd dir1 - CCACHE_BASEDIR="$(pwd)" PWD=. $CCACHE_COMPILE -I$(pwd)/include -c src/test.c + CCACHE_BASEDIR="$(pwd -P)" PWD=. $CCACHE_COMPILE -I$(pwd -P)/include -c src/test.c expect_stat direct_cache_hit 0 expect_stat preprocessed_cache_hit 0 expect_stat cache_miss 1 cd ../dir2 - CCACHE_BASEDIR="$(pwd)" PWD=. $CCACHE_COMPILE -I$(pwd)/include -c src/test.c + CCACHE_BASEDIR="$(pwd -P)" PWD=. $CCACHE_COMPILE -I$(pwd -P)/include -c src/test.c expect_stat direct_cache_hit 1 expect_stat preprocessed_cache_hit 0 expect_stat cache_miss 1 @@ -428,13 +451,13 @@ fi unset PWD cd dir1 - CCACHE_BASEDIR="$(pwd)" $CCACHE_COMPILE -I$(pwd)/include -c src/test.c + CCACHE_BASEDIR="$(pwd -P)" $CCACHE_COMPILE -I$(pwd -P)/include -c src/test.c expect_stat direct_cache_hit 0 expect_stat preprocessed_cache_hit 0 expect_stat cache_miss 1 cd ../dir2 - CCACHE_BASEDIR="$(pwd)" $CCACHE_COMPILE -I$(pwd)/include -c src/test.c + CCACHE_BASEDIR="$(pwd -P)" $CCACHE_COMPILE -I$(pwd -P)/include -c src/test.c expect_stat direct_cache_hit 1 expect_stat preprocessed_cache_hit 0 expect_stat cache_miss 1 diff --git a/unittest/test_util_path.cpp b/unittest/test_util_path.cpp index 838571ea..9ecddbcd 100644 --- a/unittest/test_util_path.cpp +++ b/unittest/test_util_path.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2024 Joel Rosdahl and other contributors +// Copyright (C) 2021-2025 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -140,12 +140,6 @@ TEST_CASE("util::make_relative_path") CHECK(make_relative_path(actual_cwd, apparent_cwd, apparent_cwd + "/x") == "x"); } - - SUBCASE("Match if using resolved (using realpath(3)) path") - { - CHECK(make_relative_path(actual_cwd, actual_cwd, apparent_cwd + "/x") - == "x"); - } #endif }