diff --git a/Sources/SwiftDriver/Driver/Driver.swift b/Sources/SwiftDriver/Driver/Driver.swift index db11ab3cc..9e856531c 100644 --- a/Sources/SwiftDriver/Driver/Driver.swift +++ b/Sources/SwiftDriver/Driver/Driver.swift @@ -2751,7 +2751,7 @@ extension Driver { } // Check that we're one of the known supported targets for sanitizers. - if !(targetTriple.isWindows || targetTriple.isDarwin || targetTriple.os == .linux) { + if !(targetTriple.isWindows || targetTriple.isDarwin || targetTriple.os == .linux || targetTriple.os == .wasi) { diagnosticEngine.emit( .error_unsupported_opt_for_target( arg: "-sanitize=", diff --git a/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift index 3ea3a2709..aee547b52 100644 --- a/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift @@ -165,8 +165,12 @@ extension WebAssemblyToolchain { // Delegate to Clang for sanitizers. It will figure out the correct linker // options. - guard sanitizers.isEmpty else { - throw Error.sanitizersUnsupportedForTarget(targetTriple.triple) + if linkerOutputType == .executable && !sanitizers.isEmpty { + let sanitizerNames = sanitizers + .map { $0.rawValue } + .sorted() // Sort so we get a stable, testable order + .joined(separator: ",") + commandLine.appendFlag("-fsanitize=\(sanitizerNames)") } if parsedOptions.hasArgument(.profileGenerate) { diff --git a/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift b/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift index 4e1fa1cd0..86748c240 100644 --- a/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift @@ -146,7 +146,12 @@ public final class WebAssemblyToolchain: Toolchain { targetTriple: Triple, isShared: Bool ) throws -> String { - throw Error.sanitizersUnsupportedForTarget(targetTriple.triple) + switch sanitizer { + case .address: + return "libclang_rt.\(sanitizer.libraryName)-\(targetTriple.archName).a" + default: + throw Error.sanitizersUnsupportedForTarget(targetTriple.triple) + } } public func platformSpecificInterpreterEnvironmentVariables(env: [String : String], diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index e3779ee48..fccc3d969 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -2877,6 +2877,47 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address"))) } #endif + + func checkWASITarget(target: String, clangOSDir: String) throws { + try withTemporaryDirectory { resourceDir in + var env = ProcessEnv.vars + env["SWIFT_DRIVER_SWIFT_AUTOLINK_EXTRACT_EXEC"] = "/garbage/swift-autolink-extract" + + let asanRuntimeLibPath = resourceDir.appending(components: [ + "clang", "lib", clangOSDir, "libclang_rt.asan-wasm32.a" + ]) + try localFileSystem.writeFileContents(asanRuntimeLibPath) { + $0.send("garbage") + } + try localFileSystem.writeFileContents(resourceDir.appending(components: "wasi", "static-executable-args.lnk")) { + $0.send("garbage") + } + + var driver = try Driver( + args: commonArgs + [ + "-target", target, "-sanitize=address", + "-resource-dir", resourceDir.pathString + ], + env: env + ) + let plannedJobs = try driver.planBuild() + + XCTAssertEqual(plannedJobs.count, 4) + + let compileJob = plannedJobs[0] + let compileCmd = compileJob.commandLine + XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address"))) + + let linkJob = plannedJobs[3] + let linkCmd = linkJob.commandLine + XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address"))) + } + } + do { + try checkWASITarget(target: "wasm32-unknown-wasi", clangOSDir: "wasi") + try checkWASITarget(target: "wasm32-unknown-wasip1", clangOSDir: "wasip1") + try checkWASITarget(target: "wasm32-unknown-wasip1-threads", clangOSDir: "wasip1") + } } func testSanitizerCoverageArgs() throws {