diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -623,6 +623,9 @@ if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY)) return errc::permission_denied; + if (Mode == AccessMode::Execute && (Attributes & FILE_ATTRIBUTE_DIRECTORY)) + return errc::permission_denied; + return std::error_code(); } diff --git a/llvm/lib/Support/Windows/Program.inc b/llvm/lib/Support/Windows/Program.inc --- a/llvm/lib/Support/Windows/Program.inc +++ b/llvm/lib/Support/Windows/Program.inc @@ -67,13 +67,10 @@ if (const char *PathExtEnv = std::getenv("PATHEXT")) SplitString(PathExtEnv, PathExts, ";"); - SmallVector U16Result; - DWORD Len = MAX_PATH; + SmallVector U8Result; for (StringRef Ext : PathExts) { - SmallVector U16Ext; - if (std::error_code EC = windows::UTF8ToUTF16(Ext, U16Ext)) - return EC; - + SmallVector U16Result; + DWORD Len = MAX_PATH; do { U16Result.reserve(Len); // Lets attach the extension manually. That is needed for files @@ -88,20 +85,24 @@ U16Result.capacity(), U16Result.data(), nullptr); } while (Len > U16Result.capacity()); - if (Len != 0) + if (Len == 0) + continue; + + U16Result.set_size(Len); + + if (std::error_code EC = + windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result)) + return EC; + + if (sys::fs::can_execute(U8Result)) break; // Found it. + + U8Result.clear(); } - if (Len == 0) + if (U8Result.empty()) return mapWindowsError(::GetLastError()); - U16Result.set_size(Len); - - SmallVector U8Result; - if (std::error_code EC = - windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result)) - return EC; - return std::string(U8Result.begin(), U8Result.end()); } diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp --- a/llvm/unittests/Support/Path.cpp +++ b/llvm/unittests/Support/Path.cpp @@ -1088,6 +1088,11 @@ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel")); } +TEST_F(FileSystemTest, DirectoryNotExecutable) { + ASSERT_EQ(fs::access(TestDirectory, sys::fs::AccessMode::Execute), + errc::permission_denied); +} + #ifdef LLVM_ON_UNIX TEST_F(FileSystemTest, BrokenSymlinkDirectoryIteration) { // Create a known hierarchy to recurse over.