Skip to content

Commit c16e0d9

Browse files
Fix FileManager.isExecutableFile for emulated x86 processes on ARM systems (#1246)
GetBinaryType will return ERROR_BAD_EXE_FORMAT when querying an arm64 executable from an x86 process running on an ARM system. This change switches the implementation to use SHGetFileInfoW, which isn't subject to this quirk. This also makes isExecutableFile behave more similarly to other platforms -- e.g. isExecutableFile already returns true for any file with the execute bit, even for an arm64 executable on an x86_64 macOS system (which it can't actually run). The spirit of the API is that the file is of an executable type, not necessarily that the running system is capable of executing it. The practical consequence of fixing this bug is that queries like: ```swift FileManager.default.isExecutableFile(atPath: "C:\\Windows\\system32\\cmd.exe") ``` will now correctly return true regardless of what architecture the binary is compiled for or what type of system it's running on. Closes #860
1 parent 78a0395 commit c16e0d9

File tree

2 files changed

+6
-2
lines changed

2 files changed

+6
-2
lines changed

Sources/FoundationEssentials/FileManager/FileManager+Files.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@ extension _FileManagerImpl {
448448
func isExecutableFile(atPath path: String) -> Bool {
449449
#if os(Windows)
450450
return (try? path.withNTPathRepresentation {
451-
var dwBinaryType: DWORD = 0
452-
return GetBinaryTypeW($0, &dwBinaryType)
451+
// Use SHGetFileInfo instead of GetBinaryType because the latter returns the wrong answer for x86 binaries running under emulation on ARM systems.
452+
return (SHGetFileInfoW($0, 0, nil, 0, SHGFI_EXETYPE) & 0xFFFF) != 0
453453
}) ?? false
454454
#else
455455
_fileAccessibleForMode(path, X_OK)

Sources/FoundationEssentials/WinSDK+Extensions.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ package var RRF_RT_REG_SZ: DWORD {
229229
DWORD(WinSDK.RRF_RT_REG_SZ)
230230
}
231231

232+
package var SHGFI_EXETYPE: UINT {
233+
UINT(WinSDK.SHGFI_EXETYPE)
234+
}
235+
232236
package var SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD {
233237
DWORD(WinSDK.SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
234238
}

0 commit comments

Comments
 (0)