Add Undefined Behavior sanitizer to Swift Driver (#18553)

This change allows the swift driver to link the ubsan runtime if
`-sanitize=undefined` is specified.
This is useful for sanitizing linked Objective-C code.
This commit is contained in:
Rahul Malik
2018-11-13 12:11:56 -08:00
committed by George Karpenkov
parent 6462473696
commit d3cc043e58
22 changed files with 56 additions and 1 deletions

View File

@@ -19,7 +19,8 @@ namespace swift {
enum class SanitizerKind : unsigned { enum class SanitizerKind : unsigned {
Address = 1 << 1, Address = 1 << 1,
Thread = 1 << 2, Thread = 1 << 2,
Fuzzer = 1 << 3 Fuzzer = 1 << 3,
Undefined = 1 << 4
}; };
} // end namespace swift } // end namespace swift

View File

@@ -360,6 +360,9 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
if (context.OI.SelectedSanitizers & SanitizerKind::Thread) if (context.OI.SelectedSanitizers & SanitizerKind::Thread)
addLinkSanitizerLibArgsForDarwin(context.Args, Arguments, "tsan", *this); addLinkSanitizerLibArgsForDarwin(context.Args, Arguments, "tsan", *this);
if (context.OI.SelectedSanitizers & SanitizerKind::Undefined)
addLinkSanitizerLibArgsForDarwin(context.Args, Arguments, "ubsan", *this);
// Only link in libFuzzer for executables. // Only link in libFuzzer for executables.
if (job.getKind() == LinkKind::Executable && if (job.getKind() == LinkKind::Executable &&
(context.OI.SelectedSanitizers & SanitizerKind::Fuzzer)) (context.OI.SelectedSanitizers & SanitizerKind::Fuzzer))

View File

@@ -301,9 +301,13 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
if (context.OI.SelectedSanitizers & SanitizerKind::Thread) if (context.OI.SelectedSanitizers & SanitizerKind::Thread)
addLinkSanitizerLibArgsForLinux(context.Args, Arguments, "tsan", *this); addLinkSanitizerLibArgsForLinux(context.Args, Arguments, "tsan", *this);
if (context.OI.SelectedSanitizers & SanitizerKind::Undefined)
addLinkSanitizerLibArgsForLinux(context.Args, Arguments, "ubsan", *this);
if (context.OI.SelectedSanitizers & SanitizerKind::Fuzzer) if (context.OI.SelectedSanitizers & SanitizerKind::Fuzzer)
addLinkRuntimeLib(context.Args, Arguments, addLinkRuntimeLib(context.Args, Arguments,
sanitizerRuntimeLibName("fuzzer")); sanitizerRuntimeLibName("fuzzer"));
} }
} }

View File

@@ -147,6 +147,10 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job,
if (context.OI.SelectedSanitizers & SanitizerKind::Address) if (context.OI.SelectedSanitizers & SanitizerKind::Address)
addLinkRuntimeLib(context.Args, Arguments, addLinkRuntimeLib(context.Args, Arguments,
sanitizerRuntimeLibName("asan")); sanitizerRuntimeLibName("asan"));
if (context.OI.SelectedSanitizers & SanitizerKind::Undefined)
addLinkRuntimeLib(context.Args, Arguments,
sanitizerRuntimeLibName("ubsan"));
} }
if (context.Args.hasArg(options::OPT_profile_generate)) { if (context.Args.hasArg(options::OPT_profile_generate)) {

View File

@@ -37,6 +37,8 @@ static StringRef toStringRef(const SanitizerKind kind) {
return "thread"; return "thread";
case SanitizerKind::Fuzzer: case SanitizerKind::Fuzzer:
return "fuzzer"; return "fuzzer";
case SanitizerKind::Undefined:
return "undefined";
} }
llvm_unreachable("Unsupported sanitizer"); llvm_unreachable("Unsupported sanitizer");
} }
@@ -49,6 +51,8 @@ static const char* toFileName(const SanitizerKind kind) {
return "tsan"; return "tsan";
case SanitizerKind::Fuzzer: case SanitizerKind::Fuzzer:
return "fuzzer"; return "fuzzer";
case SanitizerKind::Undefined:
return "ubsan";
} }
llvm_unreachable("Unsupported sanitizer"); llvm_unreachable("Unsupported sanitizer");
} }
@@ -134,6 +138,7 @@ OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
.Case("address", SanitizerKind::Address) .Case("address", SanitizerKind::Address)
.Case("thread", SanitizerKind::Thread) .Case("thread", SanitizerKind::Thread)
.Case("fuzzer", SanitizerKind::Fuzzer) .Case("fuzzer", SanitizerKind::Fuzzer)
.Case("undefined", SanitizerKind::Undefined)
.Default(None); .Default(None);
bool isShared = kind && *kind != SanitizerKind::Fuzzer; bool isShared = kind && *kind != SanitizerKind::Fuzzer;
if (!kind) { if (!kind) {

View File

@@ -1,3 +1,6 @@
/*
* Address Sanitizer Tests (asan)
*/
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-macosx10.9 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_OSX %s // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-macosx10.9 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_OSX %s
// RUN: not %swiftc_driver -driver-print-jobs -sanitize=fuzzer -target x86_64-apple-macosx10.9 -resource-dir %S/Inputs/nonexistent-resource-dir %s 2>&1 | %FileCheck -check-prefix=FUZZER_NONEXISTENT %s // RUN: not %swiftc_driver -driver-print-jobs -sanitize=fuzzer -target x86_64-apple-macosx10.9 -resource-dir %S/Inputs/nonexistent-resource-dir %s 2>&1 | %FileCheck -check-prefix=FUZZER_NONEXISTENT %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-ios7.1 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_IOSSIM %s // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-ios7.1 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_IOSSIM %s
@@ -9,6 +12,9 @@
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=ASAN_LINUX %s // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=ASAN_LINUX %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=ASAN_WINDOWS %s // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=ASAN_WINDOWS %s
/*
* Thread Sanitizer Tests (tsan)
*/
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-apple-macosx10.9 %s | %FileCheck -check-prefix=TSAN -check-prefix=TSAN_OSX %s // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-apple-macosx10.9 %s | %FileCheck -check-prefix=TSAN -check-prefix=TSAN_OSX %s
// RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86-apple-macosx10.9 %s 2>&1 | %FileCheck -check-prefix=TSAN_OSX_32 %s // RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86-apple-macosx10.9 %s 2>&1 | %FileCheck -check-prefix=TSAN_OSX_32 %s
// RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-apple-ios7.1 %s 2>&1 | %FileCheck -check-prefix=TSAN_IOSSIM %s // RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-apple-ios7.1 %s 2>&1 | %FileCheck -check-prefix=TSAN_IOSSIM %s
@@ -20,6 +26,23 @@
// RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=TSAN_WINDOWS %s // RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=TSAN_WINDOWS %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=TSAN_LINUX %s // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=thread -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=TSAN_LINUX %s
/*
* Undefined Behavior Sanitizer Tests (ubsan)
*/
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-apple-macosx10.9 %s | %FileCheck -check-prefix=UBSAN -check-prefix=UBSAN_OSX %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-apple-ios7.1 %s | %FileCheck -check-prefix=UBSAN -check-prefix=UBSAN_IOSSIM %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target arm64-apple-ios7.1 %s | %FileCheck -check-prefix=UBSAN -check-prefix=UBSAN_IOS %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-apple-tvos9.0 %s | %FileCheck -check-prefix=UBSAN -check-prefix=UBSAN_tvOS_SIM %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target arm64-apple-tvos9.0 %s | %FileCheck -check-prefix=UBSAN -check-prefix=UBSAN_tvOS %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target i386-apple-watchos2.0 %s | %FileCheck -check-prefix=UBSAN -check-prefix=UBSAN_watchOS_SIM %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target armv7k-apple-watchos2.0 %s | %FileCheck -check-prefix=UBSAN -check-prefix=UBSAN_watchOS %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=UBSAN_LINUX %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=UBSAN_WINDOWS %s
/*
* Bad Argument Tests
*/
// RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address,unknown %s 2>&1 | %FileCheck -check-prefix=BADARG %s // RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address,unknown %s 2>&1 | %FileCheck -check-prefix=BADARG %s
// RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -sanitize=unknown %s 2>&1 | %FileCheck -check-prefix=BADARG %s // RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -sanitize=unknown %s 2>&1 | %FileCheck -check-prefix=BADARG %s
// RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address,thread %s 2>&1 | %FileCheck -check-prefix=INCOMPATIBLESANITIZERS %s // RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address,thread %s 2>&1 | %FileCheck -check-prefix=INCOMPATIBLESANITIZERS %s
@@ -64,5 +87,20 @@
// TSAN: -rpath @executable_path // TSAN: -rpath @executable_path
// UBSAN: swift
// UBSAN: -sanitize=undefined
// UBSAN_OSX: lib/swift/clang/lib/darwin/libclang_rt.ubsan_osx_dynamic.dylib
// UBSAN_IOSSIM: lib/swift/clang/lib/darwin/libclang_rt.ubsan_iossim_dynamic.dylib
// UBSAN_IOS: lib/swift/clang/lib/darwin/libclang_rt.ubsan_ios_dynamic.dylib
// UBSAN_tvOS_SIM: lib/swift/clang/lib/darwin/libclang_rt.ubsan_tvossim_dynamic.dylib
// UBSAN_tvOS: lib/swift/clang/lib/darwin/libclang_rt.ubsan_tvos_dynamic.dylib
// UBSAN_watchOS_SIM: lib/swift/clang/lib/darwin/libclang_rt.ubsan_watchossim_dynamic.dylib
// UBSAN_watchOS: lib/swift/clang/lib/darwin/libclang_rt.ubsan_watchos_dynamic.dylib
// UBSAN_LINUX: lib/swift/clang/lib/linux/libclang_rt.ubsan-x86_64.a
// UBSAN_WINDOWS: lib/swift/clang/lib/windows/clang_rt.ubsan-x86_64.lib
// UBSAN: -rpath @executable_path
// BADARG: unsupported argument 'unknown' to option '-sanitize=' // BADARG: unsupported argument 'unknown' to option '-sanitize='
// INCOMPATIBLESANITIZERS: argument '-sanitize=address' is not allowed with '-sanitize=thread' // INCOMPATIBLESANITIZERS: argument '-sanitize=address' is not allowed with '-sanitize=thread'