From 40679560a6ee3faebab15b7e8c44fff7a9e5ba8a Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Wed, 17 May 2017 22:35:28 -0700 Subject: [PATCH] make `wreaddir()` handle broken `struct dirent` Some platforms do not correctly define `struct dirent` so that its `d_name` member is long enough for the longest file name. Work around such broken definitions. Fixes #4030 (cherry picked from commit a5a9ca7d3b5d85f5d3fb5133e281760c3bffb881) --- src/wutil.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/wutil.cpp b/src/wutil.cpp index 76606aee7..5b69c47f4 100644 --- a/src/wutil.cpp +++ b/src/wutil.cpp @@ -87,15 +87,22 @@ bool wreaddir_resolving(DIR *dir, const wcstring &dir_path, wcstring &out_name, } bool wreaddir(DIR *dir, wcstring &out_name) { - struct dirent d; + // We need to use a union to ensure that the dirent struct is large enough to avoid stomping on + // the stack. Some platforms incorrectly defined the `d_name[]` member as being one element + // long when it should be at least NAME_MAX + 1. + union { + struct dirent d; + char c[offsetof(struct dirent, d_name) + NAME_MAX + 1]; /* NAME_MAX is POSIX. */ + } d_u; struct dirent *result = NULL; - int retval = readdir_r(dir, &d, &result); + int retval = readdir_r(dir, &d_u.d, &result); if (retval || !result) { out_name = L""; return false; } - out_name = str2wcstring(d.d_name); + + out_name = str2wcstring(d_u.d.d_name); return true; }