diff --git a/src/test/shell/bazel/cc_integration_test.sh b/src/test/shell/bazel/cc_integration_test.sh index f411a15f1f16aa..e4e2ae752d5ab5 100755 --- a/src/test/shell/bazel/cc_integration_test.sh +++ b/src/test/shell/bazel/cc_integration_test.sh @@ -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 < pkg/example.cc < "$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 < pkg/example.cc < + +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 < pkg/example.cc < "$TEST_log" && fail "Should have failed due to $feature" || true + expect_log "runtime error: index 10 out of bounds" +} + run_suite "cc_integration_test" diff --git a/tools/cpp/unix_cc_toolchain_config.bzl b/tools/cpp/unix_cc_toolchain_config.bzl index b6e4dcdd2fca12..64e8f0c95ebb76 100644 --- a/tools/cpp/unix_cc_toolchain_config.bzl +++ b/tools/cpp/unix_cc_toolchain_config.bzl @@ -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) @@ -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", @@ -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, @@ -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,