Skip to content

Commit 7f1a56d

Browse files
authored
Merge pull request #2911 from abertelrud/eng/68374424-invoke-commands-from-fixed-locations
SwiftPM should be more resilient against random binaries named `xcrun` and `sandbox-exec` in the PATH.
2 parents 605d50e + c07ffd1 commit 7f1a56d

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

Sources/PackageLoading/ManifestLoader.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
741741
moduleCachePath.map({ AbsolutePath($0) })
742742
].compactMap({ $0 })
743743
let profile = sandboxProfile(toolsVersion: toolsVersion, cacheDirectories: cacheDirectories)
744-
cmd = ["sandbox-exec", "-p", profile] + cmd
744+
cmd = ["/usr/bin/sandbox-exec", "-p", profile] + cmd
745745
}
746746
#endif
747747

Sources/PackageLoading/MinimumDeploymentTarget.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public struct MinimumDeploymentTarget {
2525
}
2626

2727
static func computeMinimumDeploymentTarget(of binaryPath: AbsolutePath) throws -> PlatformVersion? {
28-
let runResult = try Process.popen(arguments: ["xcrun", "vtool", "-show-build", binaryPath.pathString])
28+
let runResult = try Process.popen(arguments: ["/usr/bin/xcrun", "vtool", "-show-build", binaryPath.pathString])
2929
guard let versionString = try runResult.utf8Output().components(separatedBy: "\n").first(where: { $0.contains("minos") })?.components(separatedBy: " ").last else { return nil }
3030
return PlatformVersion(versionString)
3131
}
@@ -45,7 +45,7 @@ public struct MinimumDeploymentTarget {
4545
// On macOS, we are determining the deployment target by looking at the XCTest binary.
4646
#if os(macOS)
4747
do {
48-
let runResult = try Process.popen(arguments: ["xcrun", "--sdk", sdkName, "--show-sdk-platform-path"])
48+
let runResult = try Process.popen(arguments: ["/usr/bin/xcrun", "--sdk", sdkName, "--show-sdk-platform-path"])
4949

5050
if let version = try computeXCTestMinimumDeploymentTarget(with: runResult) {
5151
return version

Tests/CommandsTests/PackageToolTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,4 +754,36 @@ final class PackageToolTests: XCTestCase {
754754
}
755755
}
756756
}
757+
758+
func testPackageLoadingCommandPathResilience() throws {
759+
#if os(macOS)
760+
fixture(name: "ValidLayouts/SingleModule") { prefix in
761+
mktmpdir { tmpdir in
762+
// Create fake `xcrun` and `sandbox-exec` commands.
763+
let fakeBinDir = tmpdir
764+
for fakeCmdName in ["xcrun", "sandbox-exec"] {
765+
let fakeCmdPath = fakeBinDir.appending(component: fakeCmdName)
766+
try localFileSystem.writeFileContents(fakeCmdPath, body: { stream in
767+
stream <<< """
768+
#!/bin/sh
769+
echo "wrong \(fakeCmdName) invoked"
770+
exit 1
771+
"""
772+
})
773+
try localFileSystem.chmod(.executable, path: fakeCmdPath)
774+
}
775+
776+
// Invoke `swift-package`, passing in the overriding `PATH` environment variable.
777+
let packageRoot = prefix.appending(component: "Library")
778+
let patchedPATH = fakeBinDir.pathString + ":" + ProcessInfo.processInfo.environment["PATH"]!
779+
let result = try SwiftPMProduct.SwiftPackage.executeProcess(["dump-package"], packagePath: packageRoot, env: ["PATH": patchedPATH])
780+
let textOutput = try result.utf8Output() + result.utf8stderrOutput()
781+
782+
// Check that the wrong tools weren't invoked. We can't just check the exit code because of fallbacks.
783+
XCTAssertNoMatch(textOutput, .contains("wrong xcrun invoked"))
784+
XCTAssertNoMatch(textOutput, .contains("wrong sandbox-exec invoked"))
785+
}
786+
}
787+
#endif
788+
}
757789
}

0 commit comments

Comments
 (0)