]> Savannah Git Hosting - gnulib.git/commitdiff
fts: avoid crash when a cycle is added while traversing
authorKamil Dudka <kdudka@redhat.com>
Wed, 11 Feb 2015 17:41:43 +0000 (18:41 +0100)
committerPádraig Brady <P@draigBrady.com>
Tue, 17 Feb 2015 02:56:36 +0000 (02:56 +0000)
This could be triggered by auto-mounting a recursive bind mount.
Reported by Michael Chapman in: https://bugzilla.redhat.com/1188498
* lib/fts.c (fts_read): Avoid removing the original hash table item
when leaving a directory that caused a cycle, and preserve the FTS_DC
flag.

ChangeLog
lib/fts.c

index 1dfa96b549054ccc10c331b509f23dfacb56f852..00936fee6e67d7576c44b243bd4a987e8b0eca2f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2015-02-16  Kamil Dudka  <kdudka@redhat.com>
+
+       fts: avoid crash when a cycle is added while traversing
+       This could be triggered by auto-mounting a recursive bind mount.
+       Reported by Michael Chapman in: https://bugzilla.redhat.com/1188498
+       * lib/fts.c (fts_read): Avoid removing the original hash table item
+       when leaving a directory that caused a cycle, and preserve the FTS_DC
+       flag.
+
 2015-02-16  Daiki Ueno  <ueno@gnu.org>
 
        uniname/uniname: support character alias
index 5cb4cb0662a92cffaa776ca900e9748a109de1eb..a2c4e52bf7d734876c445e04de875fb38c24e81d 100644 (file)
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -1091,9 +1091,15 @@ cd_dot_dot:
                 p->fts_errno = errno;
                 SET(FTS_STOP);
         }
-        p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
-        if (p->fts_errno == 0)
-                LEAVE_DIR (sp, p, "3");
+
+        /* If the directory causes a cycle, preserve the FTS_DC flag and keep
+           the corresponding dev/ino pair in the hash table.  It is going to be
+           removed when leaving the original directory.  */
+        if (p->fts_info != FTS_DC) {
+                p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+                if (p->fts_errno == 0)
+                        LEAVE_DIR (sp, p, "3");
+        }
         return ISSET(FTS_STOP) ? NULL : p;
 }