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. `weakly_canonical()` now propagates component lookup errors.
* Fix for [#205](https://github.com/gulrak/filesystem/issues/205), `copy_file()` * Fix for [#205](https://github.com/gulrak/filesystem/issues/205), `copy_file()`
now reports an error for non-regular sources. 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), * Fix for [#185](https://github.com/gulrak/filesystem/issues/185),
`lexically_normal()` now preserves unresolved parent components in relative `lexically_normal()` now preserves unresolved parent components in relative
paths. paths.

View File

@ -1910,12 +1910,15 @@ template <typename ErrorNumber>
GHC_INLINE std::string systemErrorText(ErrorNumber code = 0) GHC_INLINE std::string systemErrorText(ErrorNumber code = 0)
{ {
#if defined(GHC_OS_WINDOWS) #if defined(GHC_OS_WINDOWS)
LPVOID msgBuf; LPWSTR msgBuf = nullptr;
DWORD dw = code ? static_cast<DWORD>(code) : ::GetLastError(); 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); 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);
std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf)); if (length != 0 && msgBuf != nullptr) {
LocalFree(msgBuf); std::string msg = toUtf8(std::wstring(msgBuf, length));
return msg; LocalFree(msgBuf);
return msg;
}
return "Unknown system error " + std::to_string(dw);
#else #else
char buffer[512]; char buffer[512];
return strerror_adapter(strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer); 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(!std::string(fse.what()).empty());
CHECK(fse.path1() == "foo/bar"); CHECK(fse.path1() == "foo/bar");
CHECK(fse.path2() == "some/other"); 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() static constexpr fs::perms constExprOwnerAll()