Skip to content

Commit

Permalink
Handle F_OK case in fs__access()
Browse files Browse the repository at this point in the history
It turns out that `F_OK` is supposed to only check for path existence,
and because it is `0x00`, it ends up confusing the Windows APIs below
where it looks like we're asking for the null set of permissions.
  • Loading branch information
staticfloat committed Feb 3, 2025
1 parent b7aef5d commit 7837163
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions src/win/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2124,7 +2124,18 @@ static void fs__access(uv_fs_t* req) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
DWORD sdLen = 0, err = 0, tokenAccess = 0, executeAccessRights = 0,

/*
* If the calling code is asking for `F_OK`, it merely cares about
* path existence, which we have already determined, so early-exit
* before we start checking individual bits in `mode`.
*/
if (req->fs.info.mode == F_OK) {
SET_REQ_SUCCESS(req);
return;
}

DWORD sdLen = 0, err = 0, tokenAccess = 0, desiredAccess = 0,
grantedAccess = 0, privilegesLen = 0;
SECURITY_INFORMATION si = (SECURITY_INFORMATION)NULL;
PSECURITY_DESCRIPTOR sd = NULL;
Expand Down Expand Up @@ -2185,26 +2196,26 @@ static void fs__access(uv_fs_t* req) {
* Next, construct a mapping from generic access rights to
* the more specific access rights that AccessCheck expects.
*/
executeAccessRights = 0;
desiredAccess = 0;
if (req->fs.info.mode & R_OK) {
executeAccessRights |= FILE_GENERIC_READ;
desiredAccess |= FILE_GENERIC_READ;
mapping.GenericRead = FILE_GENERIC_READ;
}
if (req->fs.info.mode & W_OK) {
executeAccessRights |= FILE_GENERIC_WRITE;
desiredAccess |= FILE_GENERIC_WRITE;
mapping.GenericWrite = FILE_GENERIC_WRITE;
}
if (req->fs.info.mode & X_OK) {
executeAccessRights |= FILE_GENERIC_EXECUTE;
desiredAccess |= FILE_GENERIC_EXECUTE;
mapping.GenericExecute = FILE_GENERIC_EXECUTE;
}
MapGenericMask(&executeAccessRights, &mapping);
MapGenericMask(&desiredAccess, &mapping);

privilegesLen = sizeof(privileges);
result = FALSE;
if (AccessCheck(sd,
hImpersonatedToken,
executeAccessRights,
desiredAccess,
&mapping,
&privileges,
&privilegesLen,
Expand Down

0 comments on commit 7837163

Please sign in to comment.