bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 4/6] canonicalize: fix most of another EOVERFLOW issue


From: Paul Eggert
Subject: [PATCH 4/6] canonicalize: fix most of another EOVERFLOW issue
Date: Wed, 2 Dec 2020 14:39:44 -0800

* lib/canonicalize.c (canonicalize_filename_mode):
Do not call stat if fewer than 20 symlinks have been traversed.
This avoids EOVERFLOW failure in the common case where there
are not that many symlinks, while continuing to catch loops
(or fail due to EOVERFLOW) in the unusual case when there
are many symlinks to traverse.
---
 ChangeLog          | 8 ++++++++
 lib/canonicalize.c | 9 +++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 81d1c884f..a2af24dc4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2020-12-02  Paul Eggert  <eggert@cs.ucla.edu>
 
+       canonicalize: fix most of another EOVERFLOW issue
+       * lib/canonicalize.c (canonicalize_filename_mode):
+       Do not call stat if fewer than 20 symlinks have been traversed.
+       This avoids EOVERFLOW failure in the common case where there
+       are not that many symlinks, while continuing to catch loops
+       (or fail due to EOVERFLOW) in the unusual case when there
+       are many symlinks to traverse.
+
        canonicalize: do not assume symlinks have st_ino
        * lib/canonicalize.c (canonicalize_filename_mode):
        When checking for loops, use st_dev and st_ino from the parent
diff --git a/lib/canonicalize.c b/lib/canonicalize.c
index d82ad5043..2618844e8 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -107,6 +107,7 @@ canonicalize_filename_mode (const char *name, 
canonicalize_mode_t can_mode)
   int saved_errno;
   int can_flags = can_mode & ~CAN_MODE_MASK;
   bool logical = can_flags & CAN_NOLINKS;
+  int num_links = 0;
   size_t prefix_len;
 
   can_mode &= CAN_MODE_MASK;
@@ -248,9 +249,13 @@ canonicalize_filename_mode (const char *name, 
canonicalize_mode_t can_mode)
             {
               /* A physical traversal and RNAME is a symbolic link.  */
 
-              if (*start)
+              if (num_links < 20)
+                num_links++;
+              else if (*start)
                 {
-                  /* Get the device and inode of the parent directory, as
+                  /* Enough symlinks have been seen that it is time to
+                     worry about being in a symlink cycle.
+                     Get the device and inode of the parent directory, as
                      pre-2017 POSIX says this info is not reliable for
                      symlinks.  */
                   dest[- (end - start)] = '\0';
-- 
2.27.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]