aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy3
-rw-r--r--meson.build15
-rw-r--r--src/asan-options/asan-options.cc17
-rw-r--r--src/meson.build11
-rw-r--r--src/nix/meson.build1
-rw-r--r--tests/functional/repl_characterization/meson.build1
-rw-r--r--tests/functional/test-libstoreconsumer/meson.build1
-rw-r--r--tests/unit/meson.build17
8 files changed, 59 insertions, 7 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 3b5dcd91a..0cc1f2520 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -16,3 +16,6 @@ Checks:
- -bugprone-unchecked-optional-access
# many warnings, seems like a questionable lint
- -bugprone-branch-clone
+
+CheckOptions:
+ bugprone-reserved-identifier.AllowedIdentifiers: '__asan_default_options'
diff --git a/meson.build b/meson.build
index 56f447501..ed50dff78 100644
--- a/meson.build
+++ b/meson.build
@@ -199,7 +199,11 @@ configdata = { }
# Dependencies
#
-boehm = dependency('bdw-gc', required : get_option('gc'), version : '>=8.2.6')
+gc_opt = get_option('gc').disable_if(
+ 'address' in get_option('b_sanitize'),
+ error_message: 'gc does far too many memory crimes for ASan'
+)
+boehm = dependency('bdw-gc', required : gc_opt, version : '>=8.2.6')
configdata += {
'HAVE_BOEHMGC': boehm.found().to_int(),
}
@@ -482,7 +486,14 @@ if cxx.get_id() == 'clang' and get_option('b_sanitize') != ''
add_project_link_arguments('-shared-libsan', language : 'cpp')
endif
+# Clang gets grumpy about missing libasan symbols if -shared-libasan is not
+# passed when building shared libs, at least on Linux
+if cxx.get_id() == 'clang' and 'address' in get_option('b_sanitize')
+ add_project_link_arguments('-shared-libasan', language : 'cpp')
+endif
+
add_project_link_arguments('-pthread', language : 'cpp')
+
if cxx.get_linker_id() in ['ld.bfd', 'ld.gold']
add_project_link_arguments('-Wl,--no-copy-dt-needed-entries', language : 'cpp')
endif
@@ -497,7 +508,7 @@ endif
# maintainers/buildtime_report.sh BUILD-DIR to simply work in clang builds.
#
# They can also be manually viewed at https://ui.perfetto.dev
-if get_option('profile-build').require(meson.get_compiler('cpp').get_id() == 'clang').enabled()
+if get_option('profile-build').require(cxx.get_id() == 'clang').enabled()
add_project_arguments('-ftime-trace', language: 'cpp')
endif
diff --git a/src/asan-options/asan-options.cc b/src/asan-options/asan-options.cc
new file mode 100644
index 000000000..c4cf360af
--- /dev/null
+++ b/src/asan-options/asan-options.cc
@@ -0,0 +1,17 @@
+/// @file This is very bothersome code that has to be included in every
+/// executable to get the correct default ASan options. I am so sorry.
+
+extern "C" [[gnu::retain]] const char *__asan_default_options()
+{
+ // We leak a bunch of memory knowingly on purpose. It's not worthwhile to
+ // diagnose that memory being leaked for now.
+ //
+ // Instruction bytes are useful for finding the actual code that
+ // corresponds to an ASan report.
+ //
+ // TODO: setting log_path=asan.log or not: neither works, since you can't
+ // write to the fs in certain places in the testsuite, but you also cannot
+ // write arbitrarily to stderr in other places so the reports get eaten.
+ // pain 🥖
+ return "halt_on_error=1:abort_on_error=1:detect_leaks=0:print_summary=1:dump_instruction_bytes=1";
+}
diff --git a/src/meson.build b/src/meson.build
index 3fc5595b8..e918ae392 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -12,10 +12,19 @@ subdir('libmain')
# libcmd depends on everything
subdir('libcmd')
-
# The rest of the subdirectories aren't separate components,
# just source files in another directory, so we process them here.
+# Static library that just sets default ASan options. It needs to be included
+# in every executable.
+asanoptions = static_library(
+ 'libasanoptions',
+ files('asan-options/asan-options.cc'),
+)
+libasanoptions = declare_dependency(
+ link_whole: asanoptions
+)
+
build_remote_sources = files(
'build-remote/build-remote.cc',
)
diff --git a/src/nix/meson.build b/src/nix/meson.build
index 22f148fcb..97387e402 100644
--- a/src/nix/meson.build
+++ b/src/nix/meson.build
@@ -80,6 +80,7 @@ nix = executable(
profiles_md_gen,
nix2_commands_sources,
dependencies : [
+ libasanoptions,
liblixcmd,
liblixutil_mstatic,
liblixstore_mstatic,
diff --git a/tests/functional/repl_characterization/meson.build b/tests/functional/repl_characterization/meson.build
index 56410cfd2..79de9a5f5 100644
--- a/tests/functional/repl_characterization/meson.build
+++ b/tests/functional/repl_characterization/meson.build
@@ -7,6 +7,7 @@ repl_characterization_tester = executable(
'test-repl-characterization',
repl_characterization_tester_sources,
dependencies : [
+ libasanoptions,
liblixutil,
liblixutil_test_support,
sodium,
diff --git a/tests/functional/test-libstoreconsumer/meson.build b/tests/functional/test-libstoreconsumer/meson.build
index ad96aac12..63d0c97ac 100644
--- a/tests/functional/test-libstoreconsumer/meson.build
+++ b/tests/functional/test-libstoreconsumer/meson.build
@@ -2,6 +2,7 @@ libstoreconsumer_tester = executable(
'test-libstoreconsumer',
'main.cc',
dependencies : [
+ libasanoptions,
liblixutil,
liblixstore,
sodium,
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index c449b2276..55c7566bd 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -11,6 +11,10 @@
# functions, the result would be way less readable than just a bit of copypasta.
# It's only ~200 lines; better to just refactor the tests themselves which we'll want to do anyway.
+default_test_env = {
+ 'ASAN_OPTIONS': 'detect_leaks=0:halt_on_error=1:abort_on_error=1:print_summary=1:dump_instruction_bytes=1'
+}
+
libutil_test_support_sources = files(
'libutil-support/tests/cli-literate-parser.cc',
'libutil-support/tests/hash.cc',
@@ -63,6 +67,7 @@ libutil_tester = executable(
'liblixutil-tests',
libutil_tests_sources,
dependencies : [
+ libasanoptions,
rapidcheck,
gtest,
boehm,
@@ -78,7 +83,7 @@ test(
'libutil-unit-tests',
libutil_tester,
args : tests_args,
- env : {
+ env : default_test_env + {
'_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'tests/unit/libutil/data',
},
suite : 'check',
@@ -132,6 +137,7 @@ libstore_tester = executable(
'liblixstore-tests',
libstore_tests_sources,
dependencies : [
+ libasanoptions,
liblixstore_test_support,
liblixutil_test_support,
liblixstore_mstatic,
@@ -147,7 +153,7 @@ test(
'libstore-unit-tests',
libstore_tester,
args : tests_args,
- env : {
+ env : default_test_env + {
'_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'tests/unit/libstore/data',
},
suite : 'check',
@@ -196,6 +202,7 @@ libexpr_tester = executable(
'liblixexpr-tests',
libexpr_tests_sources,
dependencies : [
+ libasanoptions,
liblixexpr_test_support,
liblixstore_test_support,
liblixstore_mstatic,
@@ -214,7 +221,7 @@ test(
'libexpr-unit-tests',
libexpr_tester,
args : tests_args,
- env : {
+ env : default_test_env + {
'_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'tests/unit/libexpr/data',
},
suite : 'check',
@@ -226,6 +233,7 @@ libcmd_tester = executable(
'liblixcmd-tests',
files('libcmd/args.cc'),
dependencies : [
+ libasanoptions,
liblixcmd,
liblixutil,
liblixmain,
@@ -241,7 +249,7 @@ test(
'libcmd-unit-tests',
libcmd_tester,
args : tests_args,
- env : {
+ env : default_test_env + {
# No special meaning here, it's just a file laying around that is unlikely to go anywhere
# any time soon.
'_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'src/nix-env/buildenv.nix',
@@ -272,6 +280,7 @@ test(
'libmain-unit-tests',
libmain_tester,
args : tests_args,
+ env : default_test_env,
suite : 'check',
protocol : 'gtest',
)