I pushed this one after testing it on GNU/Linux, macOS, FreeBSD, and NetBSD to confirm the memory limit wouldn't cause any trouble.
Thanks, Pádraig, for finding the version the bug was introduced in. -- 8< -- Reported by Brian Foster in: <https://bugs.launchpad.net/ubuntu/+source/coreutils/+bug/2161155> * gnulib: Update to get commit b18879b9ed (canonicalize: Fix a missing check for symlink loops., 2026-09-25) * tests/misc/realpath.sh: Add a call to getlimits_. Add a test case. * NEWS: Mention the bug fix. --- NEWS | 6 ++++++ gnulib | 2 +- tests/misc/realpath.sh | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d2fb7e7b3..4ba02413c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,12 @@ GNU coreutils NEWS -*- outline -*- * Noteworthy changes in release ?.? (????-??-??) [?] +** Bug fixes + + 'realpath' no longer loops infinitely when resolving a symbolic link which + resolves to a path beginning with the symbolic link itself. + [bug introduced in coreutils-9.0] + ** New Features 'env' and 'printenv' now support the --quoting-style option diff --git a/gnulib b/gnulib index 106e9b238..b18879b9e 160000 --- a/gnulib +++ b/gnulib @@ -1 +1 @@ -Subproject commit 106e9b2384d08a1696fcbd40cbab52237943f208 +Subproject commit b18879b9ed0df8a9539488022a128d9f89c83c18 diff --git a/tests/misc/realpath.sh b/tests/misc/realpath.sh index 418ff2ffa..393ab1424 100755 --- a/tests/misc/realpath.sh +++ b/tests/misc/realpath.sh @@ -18,6 +18,7 @@ . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src print_ver_ realpath +getlimits_ stat_single=$(stat -c %d:%i /) || framework_failure_ stat_double=$(stat -c %d:%i //) || framework_failure_ @@ -134,4 +135,17 @@ mkdir noread && chmod a-r noread || framework_failure_ test "$(realpath noread/)" = "$(realpath .)/noread" || fail=1 test "$(realpath -e noread/)" = "$(realpath .)/noread" || fail=1 +# From coreutils 9.0 to 9.12, the following would loop until the +# system ran out of memory. +ln -s loop/a loop || framework_failure_ +vm=$(get_min_ulimit_v_ realpath .) && { + (ulimit -v $(($vm+6000)) && + returns_ 1 timeout 10 realpath loop >out 2>err) || fail=1 + cat <<EOF >exp || framework_failure_ +realpath: loop: $ELOOP +EOF + compare /dev/null out || fail=1 + compare exp err || fail=1 +} + Exit $fail -- 2.55.0
