From 442d95aa4193dc9b56889dcd9012594be9860fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schu=CC=88mann?= Date: Sun, 12 Jul 2026 10:47:39 +0200 Subject: [PATCH] Handle Windows unknown error codes safely in systemErrorText (#206) --- README.md | 2 ++ include/ghc/filesystem.hpp | 13 ++++++++----- test/filesystem_test.cpp | 7 +++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 40be530..a2826be 100644 --- a/README.md +++ b/README.md @@ -663,6 +663,8 @@ to the expected behavior. `weakly_canonical()` now propagates component lookup errors. * Fix for [#205](https://github.com/gulrak/filesystem/issues/205), `copy_file()` now reports an error for non-regular sources. +* Fix for [#206](https://github.com/gulrak/filesystem/issues/206), Windows error + formatting now handles unknown error codes safely. * Fix for [#185](https://github.com/gulrak/filesystem/issues/185), `lexically_normal()` now preserves unresolved parent components in relative paths. diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index db3daf1..a554f10 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -1910,12 +1910,15 @@ template GHC_INLINE std::string systemErrorText(ErrorNumber code = 0) { #if defined(GHC_OS_WINDOWS) - LPVOID msgBuf; + LPWSTR msgBuf = nullptr; DWORD dw = code ? static_cast(code) : ::GetLastError(); - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL); - std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf)); - LocalFree(msgBuf); - return msg; + DWORD length = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&msgBuf), 0, NULL); + if (length != 0 && msgBuf != nullptr) { + std::string msg = toUtf8(std::wstring(msgBuf, length)); + LocalFree(msgBuf); + return msg; + } + return "Unknown system error " + std::to_string(dw); #else char buffer[512]; return strerror_adapter(strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer); diff --git a/test/filesystem_test.cpp b/test/filesystem_test.cpp index 8bd4d82..85bef38 100644 --- a/test/filesystem_test.cpp +++ b/test/filesystem_test.cpp @@ -1234,6 +1234,13 @@ TEST_CASE("fs.class.filesystem_error - class filesystem_error", "[filesystem][fi CHECK(!std::string(fse.what()).empty()); CHECK(fse.path1() == "foo/bar"); CHECK(fse.path2() == "some/other"); +#if defined(GHC_OS_WINDOWS) && !defined(USE_STD_FS) + CHECK_FALSE(fs::detail::systemErrorText(ERROR_FILE_NOT_FOUND).empty()); + const DWORD unknownError = 0xffffffffu; + const auto unknownErrorText = fs::detail::systemErrorText(unknownError); + CHECK_FALSE(unknownErrorText.empty()); + CHECK(unknownErrorText.find(std::to_string(unknownError)) != std::string::npos); +#endif } static constexpr fs::perms constExprOwnerAll()