Skip to content

Add Undefined Behavior sanitizer to Swift Driver #18553

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 13, 2018

Conversation

rahul-malik
Copy link
Contributor

What's in this pull request?

This PR adds the ability to use the undefined behavior sanitizer. It accomplishes this by adding --sanitize=undefined to the Swift driver and linking the runtime library (if available) when it is specified.

This change is a dependency of adding this feature to SPM as discussed in this thread


// 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: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86-apple-macosx10.9 %s 2>&1 | %FileCheck -check-prefix=UBSAN_OSX_32 %s
// RUN: not %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-apple-ios7.1 %s 2>&1 | %FileCheck -check-prefix=UBSAN_IOSSIM %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this doesn't seem right. I'm pretty sure we support UBSan on all Apple platforms. @cheshire?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you’re right - I was largely basing these off the existing tsan tests and didn’t see the “not” prefix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also one thing I’ve been trying to find an answer for is if ubsan is supported on Windows. If so I’ll update the windows toolchain as well

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like not yet. Even if we're wrong about that, we can always add it later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I've omitted it for now. Updated the tests, let me know if this looks right

@rahul-malik rahul-malik force-pushed the rmalik-swift-driver-ubsan branch from 3cfd43b to 05575f6 Compare August 8, 2018 02:53
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target arm64-apple-tvos9.0 %s 2>&1 | %FileCheck -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 2>&1 | %FileCheck -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 2>&1 | %FileCheck -check-prefix=UBSAN_watchOS %s
// RUN: not %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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Confirm windows doesn't support ubsan

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think UBSan is supported on Windows - Clang 5.0.1 installed clang_rt.ubsan_standalone-x86_64.lib and variants on my Windows installation.

*/

// 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-apple-macosx10.9 %s 2>&1 | %FileCheck -check-prefix=UBSAN_OSX_32 %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The positive checks should be checking both -check-prefix=UBSAN and -check-prefix=UBSAN_<OS>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing! Is there a reason the Address Sanitizer Linux / Windows positive checks don't specify -check-prefix=ASAN ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect it was just a copy/paste mistake, like yours were.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, wait, no, the rpath command is Apple-platform-specific. I guess it's okay to leave those as they were.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I'll address and run the test suite locally before updating

// 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_standalone-x86_64.lib
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lib name is based off @troughton earlier comment but I believe the logic in the windows driver will look for clang_rt.ubsan-x86_64.lib so this might require an update

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you should be able to run the tests locally to find out! docs/Testing.md has information on how to run just the one test.

@rahul-malik
Copy link
Contributor Author

@jrose-apple @troughton - Thanks for the comments, updated!

@jrose-apple
Copy link
Contributor

@swift-ci Please test

@jrose-apple jrose-apple self-assigned this Aug 10, 2018
@jrose-apple jrose-apple requested a review from cheshire August 10, 2018 15:39
@swiftlang swiftlang deleted a comment from swift-ci Aug 10, 2018
@swiftlang swiftlang deleted a comment from swift-ci Aug 10, 2018
@rahul-malik
Copy link
Contributor Author

rahul-malik commented Aug 10, 2018

@jrose-apple - I ran into the same test failure locally but it doesn't quite make sense to me why -sanitize=undefined is not found given that if i pass -sanitize=undefined to the swiftc executable built for testing it works fine.

The test error:

<unknown>:0: error: unsupported option '-sanitize=undefined' for target 'x86_64-apple-macosx10.9'

This error occurs if you pass an unsupported value for -sanitize or if we are unable to locate the dylib. I'm assuming this error is the latter but I am unsure how to debug this further without knowing the actual folder hierarchy and contents in the CI environment.

@jrose-apple
Copy link
Contributor

Maybe we just don't build the UBSan support by default. @cheshire, @Rostepher?

@cheshire
Copy link

@rahul-malik Thanks! The source looks fine.
If the error is reproducible locally for you, could you try to build a debug version of the swift compiler, and use debugger to figure out what goes wrong?
IIRC the ubsan should be build by default.

The driver uses a somewhat convoluted logic to mark the sanitizer as unavailable if the file for it is not found in resource directory. Could you try putting a breakpoint there and seeing what happens?
If the file is not found, is the path wrong? In my build directory, I have a file "lib/clang/6.0.0/lib/darwin/libclang_rt.ubsan_osx.a" so it seems it should be found.

@rahul-malik
Copy link
Contributor Author

rahul-malik commented Aug 14, 2018

@cheshire - Here is the current local state. I'll keep debugging but just wanted to provide more information.

~/dev/swift-sources/build/Ninja-DebugAssert/llvm-macosx-x86_64/lib/clang/6.0.0
❯ ls lib/darwin/ | grep ubsan
libclang_rt.ubsan_minimal_osx.a
libclang_rt.ubsan_minimal_osx_dynamic.dylib
libclang_rt.ubsan_osx.a
libclang_rt.ubsan_osx_dynamic.dylib

The dylib is referenced from this method in DarwinToolchain.cpp

std::string toolchains::Darwin::sanitizerRuntimeLibName(StringRef Sanitizer,
                                                        bool shared) const {
  return (Twine("libclang_rt.") + Sanitizer + "_" +
          getDarwinLibraryNameSuffixForTriple(this->getTriple()) +
          (shared ? "_dynamic.dylib" : ".a"))
      .str();
}

Given that I would expect a lookup of libclang_rt.ubsan_osx_dynamic.dylib which should make it available.

@rahul-malik rahul-malik reopened this Aug 14, 2018
@cheshire
Copy link

@rahul-malik yeah it's weird. What if you change the lookup to use the archive file, does everything work then?

@rahul-malik
Copy link
Contributor Author

@cheshire - Thanks! Haven't been able to get back to this for a few days but will look into your suggestion tonight.

@rahul-malik
Copy link
Contributor Author

@cheshire - Changing to the static lib (.a) didn't fix the test for me locally. Any chance you can patch and help me investigate?

@cheshire
Copy link

cheshire commented Oct 8, 2018

@rahul-malik Sorry, I am still somewhat confused on what exactly the problem is and to which degree is it isolated.

Is it correct to say that the test is failing, and you could not quite understand why?
If yes, then it could be a matter of just adding an empty (stub) file to test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib, alongside many others (e.g. check out test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin).
During the test, the flag -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ is passed to the driver, and that's why the look up is performed in that folder.

Copy link

@cheshire cheshire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems you need to add empty stub files for ubsan into test/Driver/Inputs/fake-resource-dir

@rahul-malik
Copy link
Contributor Author

Thank you! Yes I was unclear how to go about resolving the missing file stub issue. I’ll update the PR next week with this change

@cheshire
Copy link

cheshire commented Oct 8, 2018

@rahul-malik NP! In general, I find that such issues are best resolved with debuggers: bisection narrows it down to the file not being found, and then debugger would let you know that it searches in a stub location.

This change allows the swift driver to link the ubsan runtime if
`-sanitize=undefined` is specified.
 - Update positive asan tests that don't contain `-check-prefix=ASAN`
 - Add ubsan to windows toolchain
@rahul-malik rahul-malik force-pushed the rmalik-swift-driver-ubsan branch from c3e3ac1 to 27fa64f Compare November 12, 2018 23:33
@rahul-malik
Copy link
Contributor Author

@cheshire @jrose-apple - Got around to updating with new inputs and rebasing the latest sources. Should be good to go 👍

@cheshire
Copy link

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 1bdab0c

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 1bdab0c

@cheshire
Copy link

There are tests failing, but none of them are the result of your patch.

@jrose-apple
Copy link
Contributor

I just merged Bruno's fix for this, so let's try again.

@swift-ci Please test

@rahul-malik
Copy link
Contributor Author

@jrose-apple @cheshire - Yay! Tests passed :) Is this PR ready to accept / merge?

@cheshire
Copy link

OK, Thanks!

@cheshire
Copy link

Should I merge it, or do you want to do it? You would need to use the "squash and merge" option.

@jrose-apple
Copy link
Contributor

Ah, external contributors don't have commit privileges by default, so you should be the one to merge it, George.

@cheshire cheshire merged commit d3cc043 into swiftlang:master Nov 13, 2018
@rahul-malik rahul-malik deleted the rmalik-swift-driver-ubsan branch November 13, 2018 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants