Skip to content

Commit dad6583

Browse files
committed
rustc_session: accumulate multiple -Zsanitizer target modifiers
When passing multiple `-Zsanitizer` flags to the compiler (e.g., `-Zsanitizer=address -Zsanitizer=shadow-call-stack`), the options parser was overwriting the previous values in `target_modifiers` instead of accumulating them. This resulted in only the last sanitizer being recorded in the crate metadata's target modifiers, even though the frontend correctly enabled all of them. The only way to provide multiple sanitizers was to combine them into a comma-separated list passed to a single `-Zsanitizer=` flag, but this does not fit well into the GN build system where different targets may pass different combinations of sanitizer flags. Consequently, this caused spurious "incompatible target modifiers" ABI mismatch errors when linking against dependencies compiled with accumulated flags (e.g., `-Zsanitizer=address,shadow-call-stack`). Fix this by entry-modifying the `target_modifiers` map to accumulate the sanitizers as a comma-separated list when the option is `sanitizer`. Also add a codegen test verifying that both CFI and SafeStack attributes/metadata are present when enabled together via multiple flags. Test: ./x.py test tests/codegen-llvm/sanitizer/multiple-sanitizers.rs
1 parent 5930afc commit dad6583

6 files changed

Lines changed: 41 additions & 5 deletions

File tree

compiler/rustc_session/src/options.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,25 @@ fn build_options<O: Default>(
726726
}
727727
if let Some(tmod) = *tmod {
728728
let v = value.map_or(String::new(), ToOwned::to_owned);
729-
collected_options.target_modifiers.insert(tmod, v);
729+
730+
// Accumulate all the -Zsanitizer flags into a single target modifier.
731+
match tmod {
732+
OptionsTargetModifiers::UnstableOptions(
733+
UnstableOptionsTargetModifiers::Sanitizer,
734+
) => {
735+
collected_options
736+
.target_modifiers
737+
.entry(tmod)
738+
.and_modify(|existing| {
739+
existing.push(',');
740+
existing.push_str(&v);
741+
})
742+
.or_insert(v);
743+
}
744+
_ => {
745+
collected_options.target_modifiers.insert(tmod, v);
746+
}
747+
}
730748
}
731749
if let Some(mitigation) = mitigation {
732750
collected_options.mitigations.reset_mitigation(*mitigation, index);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Verifies that multiple compatible sanitizers (CFI + SafeStack) can be enabled together
2+
// and their target modifiers accumulate instead of overwriting.
3+
//
4+
//@ only-x86_64
5+
//@ only-linux
6+
//@ compile-flags: -Zsanitizer=cfi -Zsanitizer=safestack -Clto -Ccodegen-units=1 -C unsafe-allow-abi-mismatch=sanitizer
7+
8+
#![crate_type = "lib"]
9+
10+
// CHECK: ; Function Attrs:{{.*}}safestack
11+
// CHECK: define{{.*}}foo{{.*}}!type
12+
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
13+
f(arg)
14+
}
15+
16+
// CHECK: attributes #0 = {{.*}}safestack{{.*}}

tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi`
2-
--> $DIR/sanitizers-safestack-and-kcfi.rs:16:1
2+
--> $DIR/sanitizers-safestack-and-kcfi.rs:18:1
33
|
44
LL | #![feature(no_core)]
55
| ^

tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi`
2-
--> $DIR/sanitizers-safestack-and-kcfi.rs:16:1
2+
--> $DIR/sanitizers-safestack-and-kcfi.rs:18:1
33
|
44
LL | #![feature(no_core)]
55
| ^

tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi`
2-
--> $DIR/sanitizers-safestack-and-kcfi.rs:16:1
2+
--> $DIR/sanitizers-safestack-and-kcfi.rs:18:1
33
|
44
LL | #![feature(no_core)]
55
| ^

tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
//@ aux-build:safestack-and-kcfi.rs
55
//@ compile-flags: -Cpanic=abort
66

7-
//@ revisions: good good_reverted missed_safestack missed_kcfi missed_both
7+
//@ revisions: good good_reverted good_multiple missed_safestack missed_kcfi missed_both
88
//@[good] compile-flags: -Zsanitizer=safestack,kcfi
99
//@[good_reverted] compile-flags: -Zsanitizer=kcfi,safestack
10+
//@[good_multiple] compile-flags: -Zsanitizer=safestack -Zsanitizer=kcfi
1011
//@[missed_safestack] compile-flags: -Zsanitizer=kcfi
1112
//@[missed_kcfi] compile-flags: -Zsanitizer=safestack
1213
// [missed_both] no additional compile-flags:
1314
//@[good] check-pass
1415
//@[good_reverted] check-pass
16+
//@[good_multiple] check-pass
1517

1618
#![feature(no_core)]
1719
//[missed_safestack]~^ ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi`

0 commit comments

Comments
 (0)