I don't have access to a machine with coreutils-5.3.0, but it appears this was introduced in commit e4ccef8ddc672f9e5ee4963db550f97c1ae2edc8 [1]. That commit changed an early return, before the FILE_STATS was used, into an error flag.
[1] https://github.com/coreutils/coreutils/commit/e4ccef8ddc672f9e5ee4963db550f97c1ae2edc8 -- 8< -- * src/chown-core.c (change_file_owner): Set the pointer to NULL if fstatat fails. * tests/chgrp/verbose-dangling-symlink.sh: New file. * tests/chown/verbose-dangling-symlink.sh: New file. * tests/local.mk (all_tests): Add the new tests. * NEWS: Mention the bug fix. Discovered by Anthropic's OSS Scanner, as bug ANT-2026-YYGC42VE. --- NEWS | 4 +++ src/chown-core.c | 7 ++-- tests/chgrp/verbose-dangling-symlink.sh | 44 ++++++++++++++++++++++++ tests/chown/verbose-dangling-symlink.sh | 45 +++++++++++++++++++++++++ tests/local.mk | 2 ++ 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100755 tests/chgrp/verbose-dangling-symlink.sh create mode 100755 tests/chown/verbose-dangling-symlink.sh diff --git a/NEWS b/NEWS index 275140f89..f4ee8761a 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,10 @@ GNU coreutils NEWS -*- outline -*- the \u0085 (next line) character as a separator on non-GLIBC platforms. [bug introduced in coreutils-9.11] + 'chown -v' and 'chgrp -v' no longer emit uninitialized user and group IDs when + operating on dangling symbolic links. + [bug introduced in coreutils-5.3.0] + 'date -u MMDDhhmm' no longer uses the local time zone's UTC offset when setting the date and time. [bug introduced in coreutils-9.11] diff --git a/src/chown-core.c b/src/chown-core.c index 21f1e3d97..4698e27eb 100644 --- a/src/chown-core.c +++ b/src/chown-core.c @@ -384,7 +384,9 @@ change_file_owner (FTS *fts, FTSENT *ent, stat it to get info on the referent. */ if (chopt->affect_symlink_referent && S_ISLNK (file_stats->st_mode)) { - if (fstatat (fts->fts_cwd_fd, file, &stat_buf, 0) != 0) + if (0 <= fstatat (fts->fts_cwd_fd, file, &stat_buf, 0)) + file_stats = &stat_buf; + else { if (ignore_missing && ignorable_traversal_errno (errno)) @@ -393,9 +395,8 @@ change_file_owner (FTS *fts, FTSENT *ent, error (0, errno, _("cannot dereference %s"), quoteaf (file_full_name)); ok = false; + file_stats = NULL; } - - file_stats = &stat_buf; } do_chown = (ok diff --git a/tests/chgrp/verbose-dangling-symlink.sh b/tests/chgrp/verbose-dangling-symlink.sh new file mode 100755 index 000000000..edf8c8c35 --- /dev/null +++ b/tests/chgrp/verbose-dangling-symlink.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Test that 'chgrp --verbose' works properly on dangling symbolic links. + +# Copyright (C) 2026 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ chgrp +getlimits_ + +ln -s missing dangling-slink || framework_failure_ + +set _ $(ls -ld dangling-slink); shift; group="$4" + +# From coreutils-5.3.0 to coreutils-9.12, this would use an +# uninitialized struct stat. Commonly, this would lead to the +# following message: +# +# failed to change group of 'dangling-slink' from root to collin +# +# Or, a random integer is being printed if the st_gid member was not +# initialized to zero by the compiler. + +echo "chgrp: cannot dereference 'dangling-slink': $ENOENT" >exp-err \ + || framework_failure_ +echo "failed to change group of 'dangling-slink' to $group" >exp-out \ + || framework_failure_ +returns_ 1 chgrp -v "$group" dangling-slink >out 2>err || fail=1 +compare exp-out out || fail=1 +compare exp-err err || fail=1 + +Exit $fail diff --git a/tests/chown/verbose-dangling-symlink.sh b/tests/chown/verbose-dangling-symlink.sh new file mode 100755 index 000000000..e64370789 --- /dev/null +++ b/tests/chown/verbose-dangling-symlink.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# Test that 'chown --verbose' works properly on dangling symbolic links. + +# Copyright (C) 2026 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ chown +getlimits_ + +ln -s missing dangling-slink || framework_failure_ + +set _ $(ls -ld dangling-slink); shift; user="$3"; group="$4" + +# From coreutils-5.3.0 to coreutils-9.12, this would use an +# uninitialized struct stat. Commonly, this would lead to the +# following message: +# +# failed to change ownership of 'dangling-slink' \ +# from root:root to collin:collin +# +# Or, random integers if the st_gid and st_uid members were not +# initialized to zero by the compiler. + +echo "chown: cannot dereference 'dangling-slink': $ENOENT" >exp-err \ + || framework_failure_ +echo "failed to change ownership of 'dangling-slink' to $user:$group" \ + >exp-out || framework_failure_ +returns_ 1 chown -v "$user":"$group" dangling-slink >out 2>err || fail=1 +compare exp-out out || fail=1 +compare exp-err err || fail=1 + +Exit $fail diff --git a/tests/local.mk b/tests/local.mk index 3cf565944..5794e79fc 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -211,6 +211,7 @@ all_tests = \ tests/tail/quote-headers.sh \ tests/chmod/no-x.sh \ tests/chgrp/basic.sh \ + tests/chgrp/verbose-dangling-symlink.sh \ tests/rm/dangling-symlink.sh \ tests/rm/dash-hint.sh \ tests/ls/ls-time.sh \ @@ -575,6 +576,7 @@ all_tests = \ tests/chown/deref.sh \ tests/chown/preserve-root.sh \ tests/chown/separator.sh \ + tests/chown/verbose-dangling-symlink.sh \ tests/cp/abuse.sh \ tests/cp/acl.sh \ tests/cp/attr-existing.sh \ -- 2.56.0
