summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2018-05-13 18:42:37 -0700
committerPádraig Brady <P@draigBrady.com>2018-05-20 23:13:32 -0700
commite90c77eb2608f23caa798a9910d8dc0f9901904a (patch)
tree3ea4c13a2cf2d8c02e79d62b8793929771a11266
parent1193175efd58883626d2b8c454b57a9490538d61 (diff)
downloadgnulib-e90c77eb2608f23caa798a9910d8dc0f9901904a.tar.gz
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
-rw-r--r--ChangeLog9
-rw-r--r--lib/fts.c1
-rw-r--r--tests/test-fts.c30
3 files changed, 38 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index cac247c1e9..78f2ee9111 100644
--- 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.
diff --git a/lib/fts.c b/lib/fts.c
index d543510595..1ccc78c116 100644
--- 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;
diff --git a/tests/test-fts.c b/tests/test-fts.c
index ad15aff52c..79eaeae8e1 100644
--- a/tests/test-fts.c
+++ b/tests/test-fts.c
@@ -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;
}