]> Savannah Git Hosting - gnulib.git/commitdiff
fts: avoid a memory leak edge case
authorPádraig Brady <P@draigBrady.com>
Mon, 14 May 2018 01:42:37 +0000 (18:42 -0700)
committerPádraig Brady <P@draigBrady.com>
Mon, 21 May 2018 06:13:32 +0000 (23:13 -0700)
* lib/fts.c (fts_open): Set an appropriate fts_level
so that an immediate fts_close() will free the allocation.
* tests/test-fts.c (fts_dealloc): Add a test case which
will trigger under valgrind or address sanitizer.
Fixes https://bugs.gnu.org/31439

ChangeLog
lib/fts.c
tests/test-fts.c

index cac247c1e9aa78e6d28daa0243ee6f93cb394971..78f2ee911184a3745545bd3aed00a98f0a6cac21 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2018-05-20  Pádraig Brady  <P@draigBrady.com>
+
+       fts: avoid a memory leak edge case
+       * lib/fts.c (fts_open): Set an appropriate fts_level
+       so that an immediate fts_close() will free the allocation.
+       * tests/test-fts.c (fts_dealloc): Add a test case which
+       will trigger under valgrind or address sanitizer.
+       Fixes https://bugs.gnu.org/31439
+
 2018-05-20  Bruno Haible  <bruno@clisp.org>
 
        wcwidth tests: Fix link error.
index d543510595d2800f0a97838e79fadee469091c88..1ccc78c116c034dfb093689493242ee40bb7b402 100644 (file)
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -546,6 +546,7 @@ fts_open (char * const *argv,
                 goto mem3;
         sp->fts_cur->fts_link = root;
         sp->fts_cur->fts_info = FTS_INIT;
+        sp->fts_cur->fts_level = 1;
         if (! setup_dir (sp))
                 goto mem3;
 
index ad15aff52c7b8f598e9790ff0a563ba8ce8d02a2..79eaeae8e142bc8928caa9337eb3db48d577f171 100644 (file)
@@ -38,6 +38,23 @@ perror_exit (char const *message, int status)
   exit (status);
 }
 
+/* alloc/dealloc to ensure structures initialized appropriately.  */
+static void
+fts_dealloc (void)
+{
+  static char dir[] = "./";
+  static char *const curr_dir[2] = { dir, 0 };
+  FTSENT *e;
+  FTS *ftsp = fts_open (curr_dir, FTS_NOSTAT | FTS_PHYSICAL | FTS_CWDFD, 0);
+  if (ftsp)
+    {
+      if (fts_close (ftsp) != 0)
+        perror_exit ("fts_close", 9);
+    }
+  else
+    perror_exit (base, 10);
+}
+
 /* Remove BASE and all files under it.  */
 static void
 remove_tree (void)
@@ -122,9 +139,15 @@ main (void)
     perror_exit (base, 6);
   while ((e = fts_read (ftsp)))
     needles_seen += strcmp (e->fts_name, "needle") == 0;
+  int fts_read_errno = errno;
   fflush (stdout);
-  if (errno)
-    perror_exit ("fts_read", 7);
+  if (fts_read_errno)
+    {
+      errno = fts_read_errno;
+      perror_exit ("fts_read", 7);
+    }
+  if (fts_close (ftsp) != 0)
+    perror_exit (base, 8);
 
   /* Report an error if we did not find the needles.  */
   if (needles_seen != needles)
@@ -140,5 +163,8 @@ main (void)
       fprintf (stderr, "fts could not remove directory\n");
       return 1;
     }
+
+  fts_dealloc ();
+
   return 0;
 }