From: Sylvestre Ledru Date: Fri, 29 May 2026 22:43:06 +0000 (+0200) Subject: tests: cover symlink-cycle detection in chmod/chown -RL X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=7aeef80298a68e3f2f61e2317efe0a475f9760ee;p=thirdparty%2Fcoreutils.git tests: cover symlink-cycle detection in chmod/chown -RL With -L, a recursive chmod/chown follows symlinks while descending; a symlink pointing back to an ancestor forms a cycle that must be detected and not descended into forever. * tests/chmod/symlinks.sh: Add a symlink-cycle case for chmod -RL. * tests/chown/deref.sh: Likewise for chown -RL. https://github.com/coreutils/coreutils/pull/274 --- diff --git a/tests/chmod/symlinks.sh b/tests/chmod/symlinks.sh index f5f87860d2..e1b01259a4 100755 --- a/tests/chmod/symlinks.sh +++ b/tests/chmod/symlinks.sh @@ -84,4 +84,15 @@ for deref in '' '--deref' '-R'; do returns_ 1 chmod 755 $deref a/dangle 2>err || fail=1 done +# A symlink pointing back to an ancestor forms a cycle. With -L, chmod +# follows symlinks while recursing, so it must detect the cycle and stop +# rather than descend into it forever. +mkdir -p cyc/b/c || framework_failure_ +ln -s "$(pwd)/cyc" cyc/b/c/d || framework_failure_ +chmod -vRL +r cyc > out 2>&1 || fail=1 +# The symlinked directory is visited exactly once... +grep -F "'cyc/b/c/d'" out > /dev/null || { cat out; fail=1; } +# ...and recursion does not re-enter it through the cycle. +grep -F "'cyc/b/c/d/b'" out > /dev/null && { cat out; fail=1; } + Exit $fail diff --git a/tests/chown/deref.sh b/tests/chown/deref.sh index 85efd66c2c..9fbb93f86f 100755 --- a/tests/chown/deref.sh +++ b/tests/chown/deref.sh @@ -35,4 +35,15 @@ EOF compare exp out || fail=1 +# A symlink pointing back to an ancestor forms a cycle. With -L, chown +# follows symlinks while recursing, so it must detect the cycle and stop +# rather than descend into it forever. +mkdir -p cyc/b/c || framework_failure_ +ln -s "$(pwd)/cyc" cyc/b/c/d || framework_failure_ +chown -vRL $user cyc > out2 2>&1 || fail=1 +# The symlinked directory is visited exactly once... +grep -F "'cyc/b/c/d'" out2 > /dev/null || { cat out2; fail=1; } +# ...and recursion does not re-enter it through the cycle. +grep -F "'cyc/b/c/d/b'" out2 > /dev/null && { cat out2; fail=1; } + Exit $fail