Merge pull request #9869 from cadenasynyster/fix/windows-opendir-file-link-loop

fix(libc): report ELOOP from opendir of a Windows file-type link loop
This commit is contained in:
Adrià authored and GitHub committed 2026-10-26 13:14:08 +01:00
commit 5e90e7569d
2 files changed
+23 -2

No files matched your search

+10 -1
View File
@@ -54,7 +54,16 @@ int NativeOpenError(DWORD error) {
NativeDirectory* OpenNative(const std::filesystem::path& path) {
const DWORD attributes = GetFileAttributesW(path.c_str());
if (attributes == INVALID_FILE_ATTRIBUTES) { errno = NativeOpenError(GetLastError()); return nullptr; }
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { errno = ENOTDIR; return nullptr; }
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
errno = ENOTDIR;
if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
const HANDLE followed = CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (followed != INVALID_HANDLE_VALUE) CloseHandle(followed);
else if (GetLastError() == ERROR_CANT_RESOLVE_FILENAME) errno = ELOOP;
}
return nullptr;
}
auto native = std::make_unique_for_overwrite<NativeDirectory>();
native->handle = CreateFileW(path.c_str(), FILE_LIST_DIRECTORY | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+13 -1
View File
@@ -173,8 +173,20 @@ int main() {
Require(closedir_nid_postfix(directory) == 0);
Require(opendir_nid_postfix((root / "missing").string().c_str()) == nullptr);
Require(*__error_nid_postfix() == 2);
#ifndef _WIN32
const auto symlinkLoop = root / "symlink-loop";
#ifdef _WIN32
if (links) {
Require(CreateSymbolicLinkW(symlinkLoop.c_str(), L"symlink-loop", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) != 0);
Require(opendir_nid_postfix(symlinkLoop.string().c_str()) == nullptr);
Require(*__error_nid_postfix() == 62);
Require(DeleteFileW(symlinkLoop.c_str()) != 0);
const auto directoryLoop = root / "directory-loop";
Require(CreateSymbolicLinkW(directoryLoop.c_str(), L"directory-loop", SYMBOLIC_LINK_FLAG_DIRECTORY | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) != 0);
Require(opendir_nid_postfix(directoryLoop.string().c_str()) == nullptr);
Require(*__error_nid_postfix() == 62);
Require(RemoveDirectoryW(directoryLoop.c_str()) != 0);
}
#else
std::filesystem::create_symlink("symlink-loop", symlinkLoop);
Require(opendir_nid_postfix(symlinkLoop.string().c_str()) == nullptr);
Require(*__error_nid_postfix() == 62);