[llvm] 9961c03 - Return `errc::no_such_file_or_directory` in `fs::access` if `GetFileAttributesW` fails (#83495)

via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 26 21:03:33 PDT 2024


Author: Jeremy Day
Date: 2024-03-26T21:03:29-07:00
New Revision: 9961c03e9ec2fc47cb42fd16141b89dd8d8e2c01

URL: https://github.com/llvm/llvm-project/commit/9961c03e9ec2fc47cb42fd16141b89dd8d8e2c01
DIFF: https://github.com/llvm/llvm-project/commit/9961c03e9ec2fc47cb42fd16141b89dd8d8e2c01.diff

LOG: Return `errc::no_such_file_or_directory` in `fs::access` if `GetFileAttributesW` fails (#83495)

Fixes https://github.com/llvm/llvm-project/issues/83046

There is a race condition when calling `GetFileAttributesW` that can
cause it to return `ERROR_ACCESS_DENIED` on a path which exists, which
is unexpected for callers using this function to check for file
existence by passing `AccessMode::Exist`. This was manifesting as a
compiler crash on Windows downstream in the Swift compiler when using
the `-index-store-path` flag (more information in
https://github.com/apple/llvm-project/issues/8224).

I looked for alternate APIs to avoid bringing in `shlwapi.h`, but didn't
see any good candidates. I'm not tied at all to this solution, any
feedback and alternative approaches are more than welcome.

Added: 
    

Modified: 
    llvm/lib/Support/Windows/Path.inc

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index 3e4c1f74161c6f..854d531ab371fc 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -623,6 +623,10 @@ std::error_code access(const Twine &Path, AccessMode Mode) {
   DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin());
 
   if (Attributes == INVALID_FILE_ATTRIBUTES) {
+    // Avoid returning unexpected error codes when querying for existence.
+    if (Mode == AccessMode::Exist)
+      return errc::no_such_file_or_directory;
+
     // See if the file didn't actually exist.
     DWORD LastError = ::GetLastError();
     if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND)


        


More information about the llvm-commits mailing list