Skip to content

Commit 234243d

Browse files
oliverleehvadehra
authored andcommitted
Add sanitizer features to unix_cc_toolchain_config
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
1 parent 1517d17 commit 234243d

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

src/test/shell/bazel/cc_integration_test.sh

+105
Original file line numberDiff line numberDiff line change
@@ -1856,4 +1856,109 @@ EOF
18561856
fi
18571857
}
18581858

1859+
# sanitizer features are opt-in so we check if the sanitizer library is
1860+
# installed and skip the test if it isn't (e.g. centos-7-openjdk-11-gcc-10)
1861+
function __is_installed() {
1862+
local lib="$1"
1863+
1864+
if [[ "$(uname -s | tr 'A-Z' 'a-z')" == "linux" ]]; then
1865+
return $(ldconfig -p | grep -q "$lib")
1866+
fi
1867+
1868+
# assume installed for darwin
1869+
}
1870+
1871+
function test_cc_toolchain_asan_feature() {
1872+
local feature=asan
1873+
__is_installed "lib$feature" || return 0
1874+
1875+
mkdir pkg
1876+
cat > pkg/BUILD <<EOF
1877+
cc_binary(
1878+
name = 'example',
1879+
srcs = ['example.cc'],
1880+
features = ['$feature'],
1881+
)
1882+
EOF
1883+
1884+
# some versions of clang will optimize away the pointer assignment and
1885+
# dereference without volatile
1886+
# https://godbolt.org/z/of8cr3P8q
1887+
cat > pkg/example.cc <<EOF
1888+
int main() {
1889+
volatile int* p;
1890+
1891+
{
1892+
volatile int x = 0;
1893+
p = &x;
1894+
}
1895+
1896+
return *p;
1897+
}
1898+
EOF
1899+
1900+
bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
1901+
expect_log "ERROR: AddressSanitizer: stack-use-after-scope"
1902+
}
1903+
1904+
function test_cc_toolchain_tsan_feature() {
1905+
local feature=tsan
1906+
__is_installed "lib$feature" || return 0
1907+
1908+
mkdir pkg
1909+
cat > pkg/BUILD <<EOF
1910+
cc_binary(
1911+
name = 'example',
1912+
srcs = ['example.cc'],
1913+
features = ['$feature'],
1914+
)
1915+
EOF
1916+
1917+
cat > pkg/example.cc <<EOF
1918+
#include <thread>
1919+
1920+
int value = 0;
1921+
1922+
void increment() {
1923+
++value;
1924+
}
1925+
1926+
int main() {
1927+
std::thread t1(increment);
1928+
std::thread t2(increment);
1929+
t1.join();
1930+
t2.join();
1931+
1932+
return value;
1933+
}
1934+
EOF
1935+
1936+
bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
1937+
expect_log "WARNING: ThreadSanitizer: data race"
1938+
}
1939+
1940+
function test_cc_toolchain_ubsan_feature() {
1941+
local feature=ubsan
1942+
__is_installed "lib$feature" || return 0
1943+
1944+
mkdir pkg
1945+
cat > pkg/BUILD <<EOF
1946+
cc_binary(
1947+
name = 'example',
1948+
srcs = ['example.cc'],
1949+
features = ['$feature'],
1950+
)
1951+
EOF
1952+
1953+
cat > pkg/example.cc <<EOF
1954+
int main() {
1955+
int array[10];
1956+
return array[10];
1957+
}
1958+
EOF
1959+
1960+
bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
1961+
expect_log "runtime error: index 10 out of bounds"
1962+
}
1963+
18591964
run_suite "cc_integration_test"

tools/cpp/unix_cc_toolchain_config.bzl

+66
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,35 @@ lto_index_actions = [
143143
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
144144
]
145145

146+
def _sanitizer_feature(name = "", specific_compile_flags = [], specific_link_flags = []):
147+
return feature(
148+
name = name,
149+
flag_sets = [
150+
flag_set(
151+
actions = all_compile_actions,
152+
flag_groups = [
153+
flag_group(flags = [
154+
"-O1",
155+
"-fno-omit-frame-pointer",
156+
"-fno-sanitize-recover=all",
157+
] + specific_compile_flags),
158+
],
159+
with_features = [
160+
with_feature_set(features = [name]),
161+
],
162+
),
163+
flag_set(
164+
actions = all_link_actions,
165+
flag_groups = [
166+
flag_group(flags = specific_link_flags),
167+
],
168+
with_features = [
169+
with_feature_set(features = [name]),
170+
],
171+
),
172+
],
173+
)
174+
146175
def _impl(ctx):
147176
tool_paths = [
148177
tool_path(name = name, path = path)
@@ -1215,6 +1244,37 @@ def _impl(ctx):
12151244
enabled = True,
12161245
)
12171246

1247+
asan_feature = _sanitizer_feature(
1248+
name = "asan",
1249+
specific_compile_flags = [
1250+
"-fsanitize=address",
1251+
"-fno-common",
1252+
],
1253+
specific_link_flags = [
1254+
"-fsanitize=address",
1255+
],
1256+
)
1257+
1258+
tsan_feature = _sanitizer_feature(
1259+
name = "tsan",
1260+
specific_compile_flags = [
1261+
"-fsanitize=thread",
1262+
],
1263+
specific_link_flags = [
1264+
"-fsanitize=thread",
1265+
],
1266+
)
1267+
1268+
ubsan_feature = _sanitizer_feature(
1269+
name = "ubsan",
1270+
specific_compile_flags = [
1271+
"-fsanitize=undefined",
1272+
],
1273+
specific_link_flags = [
1274+
"-fsanitize=undefined",
1275+
],
1276+
)
1277+
12181278
is_linux = ctx.attr.target_libc != "macosx"
12191279
libtool_feature = feature(
12201280
name = "libtool",
@@ -1255,6 +1315,9 @@ def _impl(ctx):
12551315
strip_debug_symbols_feature,
12561316
coverage_feature,
12571317
supports_pic_feature,
1318+
asan_feature,
1319+
tsan_feature,
1320+
ubsan_feature,
12581321
] + (
12591322
[
12601323
supports_start_end_lib_feature,
@@ -1290,6 +1353,9 @@ def _impl(ctx):
12901353
libtool_feature,
12911354
archiver_flags_feature,
12921355
supports_pic_feature,
1356+
asan_feature,
1357+
tsan_feature,
1358+
ubsan_feature,
12931359
] + (
12941360
[
12951361
supports_start_end_lib_feature,

0 commit comments

Comments
 (0)