summaryrefslogtreecommitdiff
path: root/tests/readdir-rand.c
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2022-10-28 12:21:29 +0100
committerSimon McVittie <smcv@collabora.com>2022-10-28 12:21:58 +0100
commit3f3a817375f8fbfc965c1357ec45a58e3ba469a0 (patch)
tree7e051b8f0cbabdf3087afc33eaba8908883d2450 /tests/readdir-rand.c
parentd731ee804de4949afaff106c8c47062e88aeb603 (diff)
downloadostree-3f3a817375f8fbfc965c1357ec45a58e3ba469a0.tar.gz
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 <smcv@collabora.com>
Diffstat (limited to 'tests/readdir-rand.c')
-rw-r--r--tests/readdir-rand.c29
1 files changed, 28 insertions, 1 deletions
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