Skip to content

Commit

Permalink
Add sanitizer features to unix_cc_toolchain_config
Browse files Browse the repository at this point in the history
There was some discussion here about adding `asan`, `tsan`, and `ubsan` features to the unix toolchains to match macos. bazel-contrib/toolchains_llvm#90 (comment)

I've taken my changes local to that project and copied it into Bazel as suggested by @fmeum. I've written some tests but I'm not sure where to place them or if it makes sense to depend on the error messages from asan/tsan/ubsan.

Closes #17083.

PiperOrigin-RevId: 501213060
Change-Id: I9d973ebe35e4fa2804d2e91df9f700a285f7b404
  • Loading branch information
oliverlee authored and Copybara-Service committed Jan 11, 2023
1 parent d47a410 commit abae5ca
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 0 deletions.
105 changes: 105 additions & 0 deletions src/test/shell/bazel/cc_integration_test.sh
Expand Up @@ -1856,4 +1856,109 @@ EOF
fi
}

# sanitizer features are opt-in so we check if the sanitizer library is
# installed and skip the test if it isn't (e.g. centos-7-openjdk-11-gcc-10)
function __is_installed() {
local lib="$1"

if [[ "$(uname -s | tr 'A-Z' 'a-z')" == "linux" ]]; then
return $(ldconfig -p | grep -q "$lib")
fi

# assume installed for darwin
}

function test_cc_toolchain_asan_feature() {
local feature=asan
__is_installed "lib$feature" || return 0

mkdir pkg
cat > pkg/BUILD <<EOF
cc_binary(
name = 'example',
srcs = ['example.cc'],
features = ['$feature'],
)
EOF

# some versions of clang will optimize away the pointer assignment and
# dereference without volatile
# https://godbolt.org/z/of8cr3P8q
cat > pkg/example.cc <<EOF
int main() {
volatile int* p;
{
volatile int x = 0;
p = &x;
}
return *p;
}
EOF

bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
expect_log "ERROR: AddressSanitizer: stack-use-after-scope"
}

function test_cc_toolchain_tsan_feature() {
local feature=tsan
__is_installed "lib$feature" || return 0

mkdir pkg
cat > pkg/BUILD <<EOF
cc_binary(
name = 'example',
srcs = ['example.cc'],
features = ['$feature'],
)
EOF

cat > pkg/example.cc <<EOF
#include <thread>
int value = 0;
void increment() {
++value;
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
return value;
}
EOF

bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
expect_log "WARNING: ThreadSanitizer: data race"
}

function test_cc_toolchain_ubsan_feature() {
local feature=ubsan
__is_installed "lib$feature" || return 0

mkdir pkg
cat > pkg/BUILD <<EOF
cc_binary(
name = 'example',
srcs = ['example.cc'],
features = ['$feature'],
)
EOF

cat > pkg/example.cc <<EOF
int main() {
int array[10];
return array[10];
}
EOF

bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
expect_log "runtime error: index 10 out of bounds"
}

run_suite "cc_integration_test"
66 changes: 66 additions & 0 deletions tools/cpp/unix_cc_toolchain_config.bzl
Expand Up @@ -143,6 +143,35 @@ lto_index_actions = [
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
]

def _sanitizer_feature(name = "", specific_compile_flags = [], specific_link_flags = []):
return feature(
name = name,
flag_sets = [
flag_set(
actions = all_compile_actions,
flag_groups = [
flag_group(flags = [
"-O1",
"-fno-omit-frame-pointer",
"-fno-sanitize-recover=all",
] + specific_compile_flags),
],
with_features = [
with_feature_set(features = [name]),
],
),
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(flags = specific_link_flags),
],
with_features = [
with_feature_set(features = [name]),
],
),
],
)

def _impl(ctx):
tool_paths = [
tool_path(name = name, path = path)
Expand Down Expand Up @@ -1215,6 +1244,37 @@ def _impl(ctx):
enabled = True,
)

asan_feature = _sanitizer_feature(
name = "asan",
specific_compile_flags = [
"-fsanitize=address",
"-fno-common",
],
specific_link_flags = [
"-fsanitize=address",
],
)

tsan_feature = _sanitizer_feature(
name = "tsan",
specific_compile_flags = [
"-fsanitize=thread",
],
specific_link_flags = [
"-fsanitize=thread",
],
)

ubsan_feature = _sanitizer_feature(
name = "ubsan",
specific_compile_flags = [
"-fsanitize=undefined",
],
specific_link_flags = [
"-fsanitize=undefined",
],
)

is_linux = ctx.attr.target_libc != "macosx"
libtool_feature = feature(
name = "libtool",
Expand Down Expand Up @@ -1255,6 +1315,9 @@ def _impl(ctx):
strip_debug_symbols_feature,
coverage_feature,
supports_pic_feature,
asan_feature,
tsan_feature,
ubsan_feature,
] + (
[
supports_start_end_lib_feature,
Expand Down Expand Up @@ -1290,6 +1353,9 @@ def _impl(ctx):
libtool_feature,
archiver_flags_feature,
supports_pic_feature,
asan_feature,
tsan_feature,
ubsan_feature,
] + (
[
supports_start_end_lib_feature,
Expand Down

0 comments on commit abae5ca

Please sign in to comment.