@@ -4065,16 +4065,20 @@ fileprivate struct TaskConstructionTests: CoreBasedTests {
40654065 }
40664066
40674067 /// Test that we properly generate commands for the compiler sanitizer features.
4068+
4069+ static let sanitizersTestData = [
4070+ (linkerDriver: "clang", expectedAddressArgument: "-fsanitize=address", expectedScudoArgument: "-fsanitize=scudo"),
4071+ (linkerDriver: "swiftc", expectedAddressArgument: "-sanitize=address", expectedScudoArgument: "-sanitize=scudo"),
4072+ ]
4073+
40684074 @Test(
40694075 .requireSDKs(.macOS),
4070- arguments:[
4071- (linkerDriver: "clang", expectedArgument: "-fsanitize=address"),
4072- (linkerDriver: "swiftc", expectedArgument: "-sanitize=address"),
4073- ],
4076+ arguments: Self.sanitizersTestData,
40744077 )
40754078 func sanitizers(
40764079 linkerDriver: String,
4077- expectedArgument: String,
4080+ expectedAddressArgument: String,
4081+ expectedScudoArgument: String,
40784082 ) async throws {
40794083 try await withTemporaryDirectory { tmpDir in
40804084 let targetName = "AppTarget"
@@ -4154,7 +4158,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests {
41544158 results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in
41554159 task.checkCommandLineContains(
41564160 [
4157- expectedArgument ,
4161+ expectedAddressArgument ,
41584162 "-fsanitize-stable-abi",
41594163 "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)",
41604164 ]
@@ -4447,6 +4451,114 @@ fileprivate struct TaskConstructionTests: CoreBasedTests {
44474451 }
44484452 }
44494453
4454+ @Test(
4455+ arguments: Self.sanitizersTestData,
4456+ )
4457+ func scudoSanitizer(
4458+ linkerDriver: String,
4459+ expectedAddressArgument: String,
4460+ expectedScudoArgument: String,
4461+ ) async throws {
4462+ let swiftVersion = try await self.swiftVersion
4463+ try await withTemporaryDirectory { tmpDir in
4464+ let targetName = "TestTargetname"
4465+ let testProject = TestProject(
4466+ "aProject",
4467+ sourceRoot: tmpDir,
4468+ groupTree: TestGroup(
4469+ "SomeFiles",
4470+ path: "Sources",
4471+ children: [
4472+ TestFile("C_file.c"),
4473+ TestFile("SwiftFile.swift"),
4474+ ]),
4475+ buildConfigurations: [
4476+ TestBuildConfiguration(
4477+ "Debug",
4478+ buildSettings: [
4479+ "INFOPLIST_FILE": "Info.plist",
4480+ "PRODUCT_NAME": "$(TARGET_NAME)",
4481+ "SWIFT_VERSION": swiftVersion,
4482+ "CLANG_USE_RESPONSE_FILE": "NO",
4483+ ],
4484+ ),
4485+ ],
4486+ targets: [
4487+ TestStandardTarget(
4488+ targetName,
4489+ type: .commandLineTool,
4490+ buildConfigurations: [
4491+ TestBuildConfiguration("Debug"),
4492+ ],
4493+ buildPhases: [
4494+ TestSourcesBuildPhase([
4495+ "C_file.c",
4496+ "SwiftFile.swift",
4497+ ]),
4498+ ],
4499+ ),
4500+ ],
4501+ )
4502+ let core = try await getCore()
4503+ let tester = try TaskConstructionTester(core, testProject)
4504+ let SRCROOT = tester.workspace.projects[0].sourceRoot.str
4505+
4506+ // Use the local filesystem since the sanitizer logic needs to access clang.
4507+ let fs = localFS
4508+
4509+ try fs.write(Path(SRCROOT).join("Info.plist"), contents: "<dict/>")
4510+
4511+ let toolchain = try #require(tester.core.toolchainRegistry.defaultToolchain)
4512+ let toolchainDirectory: Path = toolchain.path
4513+ let clangBinary = toolchainDirectory.join("./usr/bin").join(core.hostOperatingSystem.imageFormat.executableName(basename: "clang")).normalize()
4514+ let swiftcBinary = toolchainDirectory.join("./usr/bin").join(core.hostOperatingSystem.imageFormat.executableName(basename: "swiftc")).normalize()
4515+
4516+ // Check the Scudo sanitizer
4517+ await tester.checkBuild(
4518+ BuildParameters(
4519+ configuration: "Debug",
4520+ overrides: [
4521+ "ENABLE_SCUDO_SANITIZER": "YES",
4522+ "LINKER_DRIVER": linkerDriver,
4523+ ],
4524+ ),
4525+ runDestination: .host,
4526+ fs: fs,
4527+ ) { results in
4528+ results.checkTarget(targetName) { target in
4529+ // There should be one Ld task.
4530+ results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in
4531+ task.checkCommandLineContains(
4532+ [
4533+ expectedScudoArgument,
4534+ ],
4535+ )
4536+ task.checkCommandLineDoesNotContain("YES")
4537+ task.checkCommandLineDoesNotContain("NO")
4538+ }
4539+ results.checkTask(.matchTarget(target), .matchRuleType("CompileC")) { task in
4540+ task.checkCommandLineContains([
4541+ clangBinary.str,
4542+ "-fsanitize=scudo",
4543+ ])
4544+ task.checkCommandLineDoesNotContain("YES")
4545+ task.checkCommandLineDoesNotContain("NO")
4546+ }
4547+ results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in
4548+ task.checkCommandLineContains([
4549+ swiftcBinary.str,
4550+ "-sanitize=scudo",
4551+ ])
4552+ task.checkCommandLineDoesNotContain("YES")
4553+ task.checkCommandLineDoesNotContain("NO")
4554+ }
4555+ }
4556+ results.checkNoDiagnostics()
4557+ }
4558+ }
4559+ }
4560+
4561+
44504562 /// Check that missing target GUIDs are legal, not crashes.
44514563 ///
44524564 /// This is important because we allowing this to be valid can simplify the client logic in some situations.
0 commit comments