* lib/fchownat.c (rpl_fchownat) [CHOWN_TRAILING_SLASH_BUG]:
Do the right thing if fstatat fails with EOVERFLOW.
This matters only on obsolete platforms like Solaris 9,
but it’s easy to do it right.  Simplify neighboring code.
---
 ChangeLog      |  6 ++++++
 lib/fchownat.c | 23 +++++++++++------------
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d76f5f9038..08dd88a67a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2025-09-20  Paul Eggert  <egg...@cs.ucla.edu>
 
+       fchownat: fix unlikely EOVERFLOW bug
+       * lib/fchownat.c (rpl_fchownat) [CHOWN_TRAILING_SLASH_BUG]:
+       Do the right thing if fstatat fails with EOVERFLOW.
+       This matters only on obsolete platforms like Solaris 9,
+       but it’s easy to do it right.  Simplify neighboring code.
+
        fchownat: fix missing HAVE_FCHOWNAT
        * m4/fchownat.m4 (gl_FUNC_FCHOWNAT): Use AC_CHECK_FUNCS instead of
        AC_CHECK_FUNC, so that we define HAVE_FCHOWNAT if fchownat
diff --git a/lib/fchownat.c b/lib/fchownat.c
index 453810d653..3e15fde1da 100644
--- a/lib/fchownat.c
+++ b/lib/fchownat.c
@@ -1,4 +1,6 @@
-/* This function serves as replacement for a missing fchownat function,
+/* A more POSIX-compliant fchownat
+
+   This serves as replacement for a missing fchownat function,
    as well as a workaround for the fchownat bug in glibc-2.4:
     <https://lists.ubuntu.com/archives/ubuntu-users/2006-September/093218.html>
    when the buggy fchownat-with-AT_SYMLINK_NOFOLLOW operates on a symlink, it
@@ -98,17 +100,14 @@ rpl_fchownat (int fd, char const *file, uid_t owner, gid_t 
group, int flag)
     }
 # endif
 # if CHOWN_TRAILING_SLASH_BUG
-  {
-    size_t len = strlen (file);
-    struct stat st;
-    if (len && file[len - 1] == '/')
-      {
-        if (fstatat (fd, file, &st, 0))
-          return -1;
-        if (flag == AT_SYMLINK_NOFOLLOW)
-          return fchownat (fd, file, owner, group, 0);
-      }
-  }
+  if (file[0] && file[strlen (file) - 1] == '/')
+    {
+      struct stat st;
+      int r = fstatat (fd, file, &st, 0);
+      if (r < 0 && errno != EOVERFLOW)
+        return r;
+      flag &= ~AT_SYMLINK_NOFOLLOW;
+    }
 # endif
   return fchownat (fd, file, owner, group, flag);
 }
-- 
2.51.0


Reply via email to