From 3f3a817375f8fbfc965c1357ec45a58e3ba469a0 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 28 Oct 2022 12:21:29 +0100 Subject: [PATCH] readdir-rand: Copy full size of struct dirent As noted in readdir(3), in the presence of long filenames it is possible for a directory entry to be larger than `sizeof (struct dirent)`. Copy the full length instead. Signed-off-by: Simon McVittie --- tests/readdir-rand.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/readdir-rand.c b/tests/readdir-rand.c index f5d31ffb..cd3b3b09 100644 --- a/tests/readdir-rand.c +++ b/tests/readdir-rand.c @@ -40,6 +40,33 @@ # define READDIR_R "readdir_r" #endif +/* + * copy_dirent: + * @other: Another struct dirent + * + * Returns: a copy of @other. Free with g_free(). + */ +static struct dirent * +copy_dirent (const struct dirent *other) +{ + struct dirent *self; + size_t len; + + /* We can't just use sizeof (struct dirent) for the length to copy, + * because filenames are allowed to be longer than NAME_MAX bytes. */ + len = G_STRUCT_OFFSET (struct dirent, d_name) + strlen (other->d_name) + 1; + + if (len < other->d_reclen) + len = other->d_reclen; + + if (len < sizeof (struct dirent)) + len = sizeof (struct dirent); + + self = g_malloc0 (len); + memcpy (self, other, len); + return self; +} + static GHashTable *direntcache; static GMutex direntcache_lock; static gsize initialized; @@ -114,7 +141,7 @@ readdir (DIR *dirp) de = dir_entries_new (); g_hash_table_insert (direntcache, dirp, de); } - copy = g_memdup (ret, sizeof (struct dirent)); + copy = copy_dirent (ret); g_ptr_array_add (de->entries, copy); } else