Skip to content

Commit 82f7c96

Browse files
committed
Process: Check the executable pointed to by launchPath is valid.
1 parent 90debf7 commit 82f7c96

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

Foundation/Process.swift

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,11 @@ open class Process: NSObject {
241241
open func run() throws {
242242

243243
self.processLaunchedCondition.lock()
244-
244+
defer {
245+
self.processLaunchedCondition.unlock()
246+
self.processLaunchedCondition.broadcast()
247+
}
248+
245249
// Dispatch the manager thread if it isn't already running
246250

247251
Process.setup()
@@ -250,7 +254,23 @@ open class Process: NSObject {
250254
guard let launchPath = self.executableURL?.path else {
251255
throw NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError)
252256
}
253-
257+
258+
// Initial checks that the launchPath points to an executable file. posix_spawn()
259+
// can return success even if executing the program fails, eg fork() works but execve()
260+
// fails, so try and check as much as possible beforehand.
261+
try FileManager.default._fileSystemRepresentation(withPath: launchPath, { fsRep in
262+
var statInfo = stat()
263+
guard stat(fsRep, &statInfo) == 0 else {
264+
throw _NSErrorWithErrno(errno, reading: true, path: launchPath)
265+
}
266+
267+
guard statInfo.st_mode & S_IFMT == S_IFREG else {
268+
throw NSError(domain: NSCocoaErrorDomain, code: NSFileNoSuchFileError)
269+
}
270+
guard access(fsRep, X_OK) == 0 else {
271+
throw _NSErrorWithErrno(errno, reading: true, path: launchPath)
272+
}
273+
})
254274
// Convert the arguments array into a posix_spawn-friendly format
255275

256276
var args = [launchPath]
@@ -452,7 +472,7 @@ open class Process: NSObject {
452472
}
453473

454474
close(taskSocketPair[1])
455-
475+
456476
self.runLoop = RunLoop.current
457477
self.runLoopSourceContext = CFRunLoopSourceContext(version: 0,
458478
info: Unmanaged.passUnretained(self).toOpaque(),
@@ -484,9 +504,6 @@ open class Process: NSObject {
484504
isRunning = true
485505

486506
self.processIdentifier = pid
487-
488-
self.processLaunchedCondition.unlock()
489-
self.processLaunchedCondition.broadcast()
490507
}
491508

492509
open func interrupt() { NSUnimplemented() } // Not always possible. Sends SIGINT.

0 commit comments

Comments
 (0)