Handle Windows unknown error codes safely in systemErrorText (#206)

This commit is contained in:
Steffen Schümann 2026-07-12 10:47:39 +02:00
parent 998d93cdf4
commit 442d95aa41
3 changed files with 17 additions and 5 deletions

View File

@ -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.

View File

@ -1910,12 +1910,15 @@ template <typename ErrorNumber>
GHC_INLINE std::string systemErrorText(ErrorNumber code = 0)
{
#if defined(GHC_OS_WINDOWS)
LPVOID msgBuf;
LPWSTR msgBuf = nullptr;
DWORD dw = code ? static_cast<DWORD>(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<LPWSTR>(&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);

View File

@ -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()