Skip to content

Commit b194fd3

Browse files
ShreeM01oliverlee
andauthored
Add sanitizer features to unix_cc_toolchain_config (#17263)
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 Co-authored-by: Oliver Lee <[email protected]>
1 parent 795779e commit b194fd3

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
@@ -1794,4 +1794,109 @@ EOF
17941794
fi
17951795
}
17961796

1797+
# sanitizer features are opt-in so we check if the sanitizer library is
1798+
# installed and skip the test if it isn't (e.g. centos-7-openjdk-11-gcc-10)
1799+
function __is_installed() {
1800+
local lib="$1"
1801+
1802+
if [[ "$(uname -s | tr 'A-Z' 'a-z')" == "linux" ]]; then
1803+
return $(ldconfig -p | grep -q "$lib")
1804+
fi
1805+
1806+
# assume installed for darwin
1807+
}
1808+
1809+
function test_cc_toolchain_asan_feature() {
1810+
local feature=asan
1811+
__is_installed "lib$feature" || return 0
1812+
1813+
mkdir pkg
1814+
cat > pkg/BUILD <<EOF
1815+
cc_binary(
1816+
name = 'example',
1817+
srcs = ['example.cc'],
1818+
features = ['$feature'],
1819+
)
1820+
EOF
1821+
1822+
# some versions of clang will optimize away the pointer assignment and
1823+
# dereference without volatile
1824+
# https://godbolt.org/z/of8cr3P8q
1825+
cat > pkg/example.cc <<EOF
1826+
int main() {
1827+
volatile int* p;
1828+
1829+
{
1830+
volatile int x = 0;
1831+
p = &x;
1832+
}
1833+
1834+
return *p;
1835+
}
1836+
EOF
1837+
1838+
bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
1839+
expect_log "ERROR: AddressSanitizer: stack-use-after-scope"
1840+
}
1841+
1842+
function test_cc_toolchain_tsan_feature() {
1843+
local feature=tsan
1844+
__is_installed "lib$feature" || return 0
1845+
1846+
mkdir pkg
1847+
cat > pkg/BUILD <<EOF
1848+
cc_binary(
1849+
name = 'example',
1850+
srcs = ['example.cc'],
1851+
features = ['$feature'],
1852+
)
1853+
EOF
1854+
1855+
cat > pkg/example.cc <<EOF
1856+
#include <thread>
1857+
1858+
int value = 0;
1859+
1860+
void increment() {
1861+
++value;
1862+
}
1863+
1864+
int main() {
1865+
std::thread t1(increment);
1866+
std::thread t2(increment);
1867+
t1.join();
1868+
t2.join();
1869+
1870+
return value;
1871+
}
1872+
EOF
1873+
1874+
bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
1875+
expect_log "WARNING: ThreadSanitizer: data race"
1876+
}
1877+
1878+
function test_cc_toolchain_ubsan_feature() {
1879+
local feature=ubsan
1880+
__is_installed "lib$feature" || return 0
1881+
1882+
mkdir pkg
1883+
cat > pkg/BUILD <<EOF
1884+
cc_binary(
1885+
name = 'example',
1886+
srcs = ['example.cc'],
1887+
features = ['$feature'],
1888+
)
1889+
EOF
1890+
1891+
cat > pkg/example.cc <<EOF
1892+
int main() {
1893+
int array[10];
1894+
return array[10];
1895+
}
1896+
EOF
1897+
1898+
bazel run //pkg:example &> "$TEST_log" && fail "Should have failed due to $feature" || true
1899+
expect_log "runtime error: index 10 out of bounds"
1900+
}
1901+
17971902
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)
@@ -1224,6 +1253,37 @@ def _impl(ctx):
12241253
enabled = True,
12251254
)
12261255

1256+
asan_feature = _sanitizer_feature(
1257+
name = "asan",
1258+
specific_compile_flags = [
1259+
"-fsanitize=address",
1260+
"-fno-common",
1261+
],
1262+
specific_link_flags = [
1263+
"-fsanitize=address",
1264+
],
1265+
)
1266+
1267+
tsan_feature = _sanitizer_feature(
1268+
name = "tsan",
1269+
specific_compile_flags = [
1270+
"-fsanitize=thread",
1271+
],
1272+
specific_link_flags = [
1273+
"-fsanitize=thread",
1274+
],
1275+
)
1276+
1277+
ubsan_feature = _sanitizer_feature(
1278+
name = "ubsan",
1279+
specific_compile_flags = [
1280+
"-fsanitize=undefined",
1281+
],
1282+
specific_link_flags = [
1283+
"-fsanitize=undefined",
1284+
],
1285+
)
1286+
12271287
is_linux = ctx.attr.target_libc != "macosx"
12281288
libtool_feature = feature(
12291289
name = "libtool",
@@ -1265,6 +1325,9 @@ def _impl(ctx):
12651325
strip_debug_symbols_feature,
12661326
coverage_feature,
12671327
supports_pic_feature,
1328+
asan_feature,
1329+
tsan_feature,
1330+
ubsan_feature,
12681331
] + (
12691332
[
12701333
supports_start_end_lib_feature,
@@ -1300,6 +1363,9 @@ def _impl(ctx):
13001363
libtool_feature,
13011364
archiver_flags_feature,
13021365
supports_pic_feature,
1366+
asan_feature,
1367+
tsan_feature,
1368+
ubsan_feature,
13031369
] + (
13041370
[
13051371
supports_start_end_lib_feature,

0 commit comments

Comments
 (0)