From f84c2851beb0ccdc4d8baeef218e4e2992ecf6ab Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 31 Jan 2022 21:35:48 +0000 Subject: [PATCH] Fix SHGetPathFromIDListLongPath (#16545) The function did not truncate the string afterwards, so you ended up with a very long string containing null terminators on the end. This wouldn't have caused an issue when passing it as a char *, but due to it now being passed as string or string_view, this causes issues. It also wouldn't have worked for paths greater than MAX_PATH, because it wasn't passing the buffer size to the function. --- src/openrct2-ui/UiContext.Win32.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/openrct2-ui/UiContext.Win32.cpp b/src/openrct2-ui/UiContext.Win32.cpp index 5bad0c6e53..c33267f4ba 100644 --- a/src/openrct2-ui/UiContext.Win32.cpp +++ b/src/openrct2-ui/UiContext.Win32.cpp @@ -41,17 +41,26 @@ static std::wstring SHGetPathFromIDListLongPath(LPCITEMIDLIST pidl) { +# if defined(__MINGW32__) std::wstring pszPath(MAX_PATH, 0); - while (!SHGetPathFromIDListW(pidl, &pszPath[0])) + auto result = SHGetPathFromIDListW(pidl, pszPath.data()); +# else + // Limit path length to 32K + std::wstring pszPath(std::numeric_limits().max(), 0); + auto result = SHGetPathFromIDListEx(pidl, pszPath.data(), static_cast(pszPath.size()), GPFIDL_DEFAULT); +# endif + if (result) { - if (pszPath.size() >= SHRT_MAX) + // Truncate at first null terminator + auto length = pszPath.find(L'\0'); + if (length != std::wstring::npos) { - // Clearly not succeeding at all, bail - return std::wstring(); + pszPath.resize(length); + pszPath.shrink_to_fit(); } - pszPath.resize(pszPath.size() * 2); + return pszPath; } - return pszPath; + return std::wstring(); } namespace OpenRCT2::Ui