]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
canonicalize-lgpl: sync from glibc master
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 10 Aug 2026 20:08:08 +0000 (13:08 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 10 Aug 2026 20:42:42 +0000 (13:42 -0700)
Merge into lib/canonicalize-lgpl.c the changes of glibc
stdlib/canonicalize.c through glibc commit
b589bd672c529cf264dc6dfdfa11f73c7e4e1666 dated today.
The result should be copiable back to glibc byte-for-byte.
The original motivation for this merge was to make
eloop-threshold.h thread-safe on all platforms.
It turned out that glibc has already done this, trivially,
by having the include file define a constant 40 rather than a function.
This conforms to POSIX on all glibc targets, and it should also
work on all Gnulib targets that I know of,
as sysconf (_SC_SYMLOOP_MAX) <= 40 on all known platforms.
POSIX allows us to follow more symlink expansions than
any nonnegative number returned by sysconf (_SC_SYMLOOP_MAX),
and if that number is negative POSIX requires only to expand
at least 8 symlinks so the glibc value of 40 is good then too.
* NEWS: Mention the incompatible change.
* config/srclist.txt: Add lib/min-eloop-threshold.h.
* lib/canonicalize-lgpl.c [_LIBC]: Include <stdbool.h>.
(__rawmemchr): Remove.  Replace its use with strchr.
* lib/min-eloop-threshold.h: Sync byte-for-byte from gnulibc,
renaming the file from lib/eloop-threshold.h.  All uses changed.
This entails the following changes:
(_MIN_ELOOP_THRESHOLD_H): Rename from _ELOOP_THRESHOLD_H.
All uses changed.
Don’t #error out if config.h is not already included.
Don’t include <limits.h>.
[_LIBC]: Don’t include <sys/param.h>.
(_GL_ATTRIBUTE_CONST) [_LIBC]: Remove.
[!_LIBC]: Don’t include <unistd.h>, "minmax.h".
(__sysconf, SYMLOOP_MAX) [!_LIBC]: Remove.
(MIN_ELOOP_THRESHOLD): Define unconditionally.
(__eloop_threshold): Remove.  All uses replaced by MIN_ELOOP_THRESHOLD.
The new expression is of type int not unsigned, but that’s better
for callers anyway.
* lib/openat2.c (do_openat2): Symlink count is now int, not long int.
* modules/eloop-threshold (Files, Include): Adjust to file name change.
(Depends-on): Remove minmax, unistd-h.

ChangeLog
NEWS
config/srclist.txt
lib/canonicalize-lgpl.c
lib/eloop-threshold.h [deleted file]
lib/linkat.c
lib/min-eloop-threshold.h [new file with mode: 0644]
lib/openat2.c
modules/eloop-threshold

index fade982eb5188ccaa8f0063f57dfd37b02e77dd2..e258e18d2b172d33e7cd0c3abfbb723476d31aa6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2026-08-10  Paul Eggert  <eggert@cs.ucla.edu>
+
+       canonicalize-lgpl: sync from glibc
+       Merge into lib/canonicalize-lgpl.c the changes of glibc
+       stdlib/canonicalize.c through glibc commit
+       b589bd672c529cf264dc6dfdfa11f73c7e4e1666 dated today.
+       The result should be copiable back to glibc byte-for-byte.
+       The original motivation for this merge was to make
+       eloop-threshold.h thread-safe on all platforms.
+       It turned out that glibc has already done this, trivially,
+       by having the include file define a constant 40 rather than a function.
+       This conforms to POSIX on all glibc targets, and it should also
+       work on all Gnulib targets that I know of,
+       as sysconf (_SC_SYMLOOP_MAX) <= 40 on all known platforms.
+       POSIX allows us to follow more symlink expansions than
+       any nonnegative number returned by sysconf (_SC_SYMLOOP_MAX),
+       and if that number is negative POSIX requires only to expand
+       at least 8 symlinks so the glibc value of 40 is good then too.
+       * NEWS: Mention the incompatible change.
+       * config/srclist.txt: Add lib/min-eloop-threshold.h.
+       * lib/canonicalize-lgpl.c [_LIBC]: Include <stdbool.h>.
+       (__rawmemchr): Remove.  Replace its use with strchr.
+       * lib/min-eloop-threshold.h: Sync byte-for-byte from gnulibc,
+       renaming the file from lib/eloop-threshold.h.  All uses changed.
+       This entails the following changes:
+       (_MIN_ELOOP_THRESHOLD_H): Rename from _ELOOP_THRESHOLD_H.
+       All uses changed.
+       Don’t #error out if config.h is not already included.
+       Don’t include <limits.h>.
+       [_LIBC]: Don’t include <sys/param.h>.
+       (_GL_ATTRIBUTE_CONST) [_LIBC]: Remove.
+       [!_LIBC]: Don’t include <unistd.h>, "minmax.h".
+       (__sysconf, SYMLOOP_MAX) [!_LIBC]: Remove.
+       (MIN_ELOOP_THRESHOLD): Define unconditionally.
+       (__eloop_threshold): Remove.  All uses replaced by MIN_ELOOP_THRESHOLD.
+       The new expression is of type int not unsigned, but that’s better
+       for callers anyway.
+       * lib/openat2.c (do_openat2): Symlink count is now int, not long int.
+       * modules/eloop-threshold (Files, Include): Adjust to file name change.
+       (Depends-on): Remove minmax, unistd-h.
+
 2026-08-09  Paul Eggert  <eggert@cs.ucla.edu>
 
        hamt: port to non-_Atomic C platforms
diff --git a/NEWS b/NEWS
index db7776ee781427ed635949ac1444a424a206b46b..28a5869ee8764fc9644a7584dffb6cc092e25429 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -78,6 +78,10 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2026-08-10  eloop-threshold Now include <min-eloop-threshold.h> and use
+                            MIN_ELOOP_THRESHOLD rather than including
+                            <eloop-threshold.h> and using __eloop_threshold ().
+
 2026-06-26  bitrotate       This module is deprecated.  Use stdc_rotate_left
                             or stdc_rotate_right instead.
 
index c9e6b4336ef20da9e0beee7d5d9866eb41add5d9..a19a8b78ba858723414a8e160fa5ab65e096052d 100644 (file)
@@ -89,7 +89,7 @@ $LIBCSRC stdlib/tst-stdc_leading_ones.c               tests/from-glibc
 $LIBCSRC stdlib/tst-stdc_leading_zeros.c       tests/from-glibc
 $LIBCSRC stdlib/tst-stdc_trailing_ones.c       tests/from-glibc
 $LIBCSRC stdlib/tst-stdc_trailing_zeros.c      tests/from-glibc
-#$LIBCSRC sysdeps/generic/eloop-threshold.h    lib
+$LIBCSRC sysdeps/generic/min-eloop-threshold.h lib
 #$LIBCSRC time/timegm.c                        lib
 #$LIBCSRC time/mktime.c                        lib
 #$LIBCSRC time/mktime-internal.h       lib
index a87d46a4339a622ab381a99d4b67af4a3a0b7e26..92c96243c2389195d70906b7d3ed822b38addce2 100644 (file)
@@ -34,7 +34,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include <eloop-threshold.h>
+#include <min-eloop-threshold.h>
 #include <filename.h>
 #include <idx.h>
 #include <intprops.h>
@@ -42,6 +42,7 @@
 
 #ifdef _LIBC
 # include <shlib-compat.h>
+# include <stdbool.h>
 # define GCC_LINT 1
 # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
 #else
@@ -72,7 +73,6 @@
 # endif
 # define __mempcpy mempcpy
 # define __pathconf pathconf
-# define __rawmemchr rawmemchr
 # define __readlink readlink
 # if IN_RELOCWRAPPER
     /* When building the relocatable program wrapper, use the system's memmove
@@ -233,7 +233,7 @@ realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs)
             return NULL;
           rname = bufs->rname.data;
         }
-      dest = __rawmemchr (rname, '\0');
+      dest = strchr (rname, '\0');
       start = name;
       prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
     }
@@ -317,7 +317,7 @@ realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs)
             }
           if (0 <= n)
             {
-              if (++num_links > __eloop_threshold ())
+              if (++num_links > MIN_ELOOP_THRESHOLD)
                 {
                   __set_errno (ELOOP);
                   goto error;
diff --git a/lib/eloop-threshold.h b/lib/eloop-threshold.h
deleted file mode 100644 (file)
index 3e33a24..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Threshold at which to diagnose ELOOP.  Generic version.
-   Copyright (C) 2012-2026 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#ifndef _ELOOP_THRESHOLD_H
-#define _ELOOP_THRESHOLD_H      1
-
-/* This file uses _GL_ATTRIBUTE_CONST.  */
-#if !_LIBC && !_GL_CONFIG_H_INCLUDED
- #error "Please include config.h first."
-#endif
-
-#include <limits.h>
-#ifdef _LIBC
-# include <sys/param.h>
-# define _GL_ATTRIBUTE_CONST __attribute__ ((const))
-#else
-# include <unistd.h>
-# include "minmax.h"
-# define __sysconf sysconf
-# if (!defined SYMLOOP_MAX \
-      && ! (defined _SC_SYMLOOP_MAX && defined _POSIX_SYMLOOP_MAX))
-#  define SYMLOOP_MAX 8
-# endif
-#endif
-
-/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic
-   links that can be reliably traversed in the resolution of a
-   pathname in the absence of a loop."  This makes it a minimum that
-   we should certainly accept.  But it leaves open the possibility
-   that more might sometimes work--just not "reliably".
-
-   For example, Linux implements a complex policy whereby there is a
-   small limit on the number of direct symlink traversals (a symlink
-   to a symlink to a symlink), but larger limit on the total number of
-   symlink traversals overall.  Hence the SYMLOOP_MAX number should be
-   the small one, but the limit library functions enforce on users
-   should be the larger one.
-
-   So, we use the larger of the reported SYMLOOP_MAX (if any) and our
-   own constant MIN_ELOOP_THRESHOLD, below.  This constant should be
-   large enough that it never rules out a file name and directory tree
-   that the underlying system (i.e. calls to 'open' et al) would
-   resolve successfully.  It should be small enough that actual loops
-   are detected without a huge number of iterations.  */
-
-#ifndef MIN_ELOOP_THRESHOLD
-# define MIN_ELOOP_THRESHOLD    40
-#endif
-
-/* Return the maximum number of symlink traversals to permit
-   before diagnosing ELOOP.  */
-static inline unsigned int _GL_ATTRIBUTE_CONST
-__eloop_threshold (void)
-{
-#ifdef SYMLOOP_MAX
-  const int symloop_max = SYMLOOP_MAX;
-#else
-  /* The function is marked 'const' even though we use memory and
-     call a function, because sysconf is required to return the
-     same value in every call and so it must always be safe to
-     call __eloop_threshold exactly once and reuse the value.  */
-  static long int sysconf_symloop_max;
-  if (sysconf_symloop_max == 0)
-    sysconf_symloop_max = __sysconf (_SC_SYMLOOP_MAX);
-  const unsigned int symloop_max = (sysconf_symloop_max <= 0
-                                    ? _POSIX_SYMLOOP_MAX
-                                    : sysconf_symloop_max);
-#endif
-
-  return MAX (symloop_max, MIN_ELOOP_THRESHOLD);
-}
-
-#endif  /* eloop-threshold.h */
index 0225e41d4aeeff2a4da7cbea95bf0fb70f090358..8fc105fe99374d1e867bf67b75b30c9c7572f8ed 100644 (file)
@@ -29,8 +29,8 @@
 
 #include "areadlink.h"
 #include "dirname.h"
-#include "eloop-threshold.h"
 #include "filenamecat.h"
+#include "min-eloop-threshold.h"
 #include "openat-priv.h"
 
 #if !HAVE_LINKAT || LINKAT_SYMLINK_NOTSUP
@@ -92,7 +92,7 @@ link_follow (char const *file1, char const *file2)
 {
   char *name = (char *) file1;
   char *target;
-  int i = __eloop_threshold ();
+  int i = MIN_ELOOP_THRESHOLD;
 
   /* Using realpath or canonicalize_file_name is too heavy-handed: we
      don't need an absolute name, and we don't need to resolve
@@ -209,7 +209,7 @@ linkat_follow (int fd1, char const *file1, int fd2, char const *file2)
 {
   char *name = (char *) file1;
   char *target;
-  int i = __eloop_threshold ();
+  int i = MIN_ELOOP_THRESHOLD;
 
   /* There is no realpathat.  */
   while (i-- && (target = areadlinkat (fd1, name)))
diff --git a/lib/min-eloop-threshold.h b/lib/min-eloop-threshold.h
new file mode 100644 (file)
index 0000000..26b0795
--- /dev/null
@@ -0,0 +1,42 @@
+/* Minimum threshold at which to diagnose ELOOP.  Generic version.
+   Copyright (C) 2012-2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _MIN_ELOOP_THRESHOLD_H
+#define _MIN_ELOOP_THRESHOLD_H      1
+
+/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic
+   links that can be reliably traversed in the resolution of a
+   pathname in the absence of a loop."  This makes it a minimum that
+   we should certainly accept.  But it leaves open the possibility
+   that more might sometimes work--just not "reliably".
+
+   For example, Linux implements a complex policy whereby there is a
+   small limit on the number of direct symlink traversals (a symlink
+   to a symlink to a symlink), but larger limit on the total number of
+   symlink traversals overall.  Hence the SYMLOOP_MAX number should be
+   the small one, but the limit library functions enforce on users
+   should be the larger one.
+
+   This constant should be large enough that it never rules out a file
+   name and directory tree that the underlying system (i.e. calls to 'open'
+   et al) would resolve successfully.  It should be small enough that
+   actual loops are detected without a huge number of iterations.  */
+
+#define MIN_ELOOP_THRESHOLD    40
+
+#endif
index ff8ce302632a3d63847410088eebcf092a519a3e..e860252654106333c889d2011d9d116acf6e8781 100644 (file)
 
 #include <fcntl.h>
 
-#include "eloop-threshold.h"
 #include "filename.h"
 #include "ialloc.h"
 #include "idx.h"
+#include "min-eloop-threshold.h"
 #include "verify.h"
 
 #include <errno.h>
@@ -228,7 +228,7 @@ do_openat2 (int *fd, char const *filename,
   dev_t const UNKNOWN_DEV = -1;
   dev_t ddev = UNKNOWN_DEV;
 
-  long int maxlinks = resolve & RESOLVE_NO_SYMLINKS ? 0 : __eloop_threshold ();
+  int maxlinks = resolve & RESOLVE_NO_SYMLINKS ? 0 : MIN_ELOOP_THRESHOLD;
 
   int dfd = *fd;
 
index 3cb5834cc63ead54064d86dd8424c7fe9da8318d..9a95eb54ada8c712aeb83d2349cc4e8099d2f3b9 100644 (file)
@@ -2,18 +2,16 @@ Description:
 Threshold for symbolic link loops and ELOOP
 
 Files:
-lib/eloop-threshold.h
+lib/min-eloop-threshold.h
 
 Depends-on:
-minmax
-unistd-h
 
 configure.ac:
 
 Makefile.am:
 
 Include:
-<eloop-threshold.h>
+<min-eloop-threshold.h>
 
 License:
 LGPLv2+