Skip to content

Commit 5065123

Browse files
committed
Auto merge of rust-lang#124676 - djkoloski:relax_multiple_sanitizers, r=cuviper,rcvalle
Relax restrictions on multiple sanitizers Most combinations of LLVM sanitizers are legal-enough to enable simultaneously. This change will allow simultaneously enabling ASAN and shadow call stacks on supported platforms. I used this python script to generate the mutually-exclusive sanitizer combinations: ```python #!/usr/bin/python3 import subprocess flags = [ ["-fsanitize=address"], ["-fsanitize=leak"], ["-fsanitize=memory"], ["-fsanitize=thread"], ["-fsanitize=hwaddress"], ["-fsanitize=cfi", "-flto", "-fvisibility=hidden"], ["-fsanitize=memtag", "--target=aarch64-linux-android", "-march=armv8a+memtag"], ["-fsanitize=shadow-call-stack"], ["-fsanitize=kcfi", "-flto", "-fvisibility=hidden"], ["-fsanitize=kernel-address"], ["-fsanitize=safe-stack"], ["-fsanitize=dataflow"], ] for i in range(len(flags)): for j in range(i): command = ["clang++"] + flags[i] + flags[j] + ["-o", "main.o", "-c", "main.cpp"] completed = subprocess.run(command, stderr=subprocess.DEVNULL) if completed.returncode != 0: first = flags[i][0][11:].replace('-', '').upper() second = flags[j][0][11:].replace('-', '').upper() print(f"(SanitizerSet::{first}, SanitizerSet::{second}),") ```
2 parents 6715446 + 1e1143c commit 5065123

File tree

5 files changed

+44
-22
lines changed

5 files changed

+44
-22
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,10 @@ fn add_sanitizer_libraries(
12301230
if sanitizer.contains(SanitizerSet::DATAFLOW) {
12311231
link_sanitizer_runtime(sess, flavor, linker, "dfsan");
12321232
}
1233-
if sanitizer.contains(SanitizerSet::LEAK) {
1233+
if sanitizer.contains(SanitizerSet::LEAK)
1234+
&& !sanitizer.contains(SanitizerSet::ADDRESS)
1235+
&& !sanitizer.contains(SanitizerSet::HWADDRESS)
1236+
{
12341237
link_sanitizer_runtime(sess, flavor, linker, "lsan");
12351238
}
12361239
if sanitizer.contains(SanitizerSet::MEMORY) {

compiler/rustc_session/src/session.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -1183,9 +1183,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
11831183
});
11841184
}
11851185
}
1186-
// Cannot mix and match sanitizers.
1187-
let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter();
1188-
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
1186+
1187+
// Cannot mix and match mutually-exclusive sanitizers.
1188+
if let Some((first, second)) = sess.opts.unstable_opts.sanitizer.mutually_exclusive() {
11891189
sess.dcx().emit_err(errors::CannotMixAndMatchSanitizers {
11901190
first: first.to_string(),
11911191
second: second.to_string(),
@@ -1220,14 +1220,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
12201220
sess.dcx().emit_err(errors::SanitizerCfiRequiresSingleCodegenUnit);
12211221
}
12221222

1223-
// LLVM CFI is incompatible with LLVM KCFI.
1224-
if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
1225-
sess.dcx().emit_err(errors::CannotMixAndMatchSanitizers {
1226-
first: "cfi".to_string(),
1227-
second: "kcfi".to_string(),
1228-
});
1229-
}
1230-
12311223
// Canonical jump tables requires CFI.
12321224
if sess.is_sanitizer_cfi_canonical_jump_tables_disabled() {
12331225
if !sess.is_sanitizer_cfi_enabled() {

compiler/rustc_target/src/spec/mod.rs

+35
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,34 @@ bitflags::bitflags! {
13171317
rustc_data_structures::external_bitflags_debug! { SanitizerSet }
13181318

13191319
impl SanitizerSet {
1320+
// Taken from LLVM's sanitizer compatibility logic:
1321+
// https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/Driver/SanitizerArgs.cpp#L512
1322+
const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1323+
(SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1324+
(SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1325+
(SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1326+
(SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1327+
(SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1328+
(SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1329+
(SanitizerSet::LEAK, SanitizerSet::MEMORY),
1330+
(SanitizerSet::LEAK, SanitizerSet::THREAD),
1331+
(SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1332+
(SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1333+
(SanitizerSet::MEMORY, SanitizerSet::THREAD),
1334+
(SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1335+
(SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1336+
(SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1337+
(SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1338+
(SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1339+
(SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1340+
(SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1341+
(SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1342+
(SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1343+
(SanitizerSet::CFI, SanitizerSet::KCFI),
1344+
(SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1345+
(SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1346+
];
1347+
13201348
/// Return sanitizer's name
13211349
///
13221350
/// Returns none if the flags is a set of sanitizers numbering not exactly one.
@@ -1337,6 +1365,13 @@ impl SanitizerSet {
13371365
_ => return None,
13381366
})
13391367
}
1368+
1369+
pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1370+
Self::MUTUALLY_EXCLUSIVE
1371+
.into_iter()
1372+
.find(|&(a, b)| self.contains(*a) && self.contains(*b))
1373+
.copied()
1374+
}
13401375
}
13411376

13421377
/// Formats a sanitizer set as a comma separated list of sanitizers' names.

tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.aarch64.stderr

+1-5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,5 @@ error: cfi sanitizer is not supported for this target
22

33
error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
44

5-
error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
6-
|
7-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
8-
9-
error: aborting due to 3 previous errors
5+
error: aborting due to 2 previous errors
106

tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.x86_64.stderr

+1-5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,5 @@ error: cfi sanitizer is not supported for this target
22

33
error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
44

5-
error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
6-
|
7-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
8-
9-
error: aborting due to 3 previous errors
5+
error: aborting due to 2 previous errors
106

0 commit comments

Comments
 (0)