From 115338beb8bb6f3294caa4c5fe9018560ba3b285 Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Thu, 11 Jun 2026 20:25:24 +0000 Subject: [PATCH] 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 --- compiler/rustc_session/src/options.rs | 20 ++++++++++++++++++- .../sanitizer/multiple-sanitizers.rs | 18 +++++++++++++++++ ...zers-safestack-and-kcfi.missed_both.stderr | 2 +- ...zers-safestack-and-kcfi.missed_kcfi.stderr | 2 +- ...safestack-and-kcfi.missed_safestack.stderr | 2 +- .../sanitizers-safestack-and-kcfi.rs | 4 +++- 6 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 tests/codegen-llvm/sanitizer/multiple-sanitizers.rs diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0582791dad005..e80f89edb485f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -726,7 +726,25 @@ fn build_options( } if let Some(tmod) = *tmod { let v = value.map_or(String::new(), ToOwned::to_owned); - collected_options.target_modifiers.insert(tmod, v); + + // Accumulate all the -Zsanitizer flags into a single target modifier. + match tmod { + OptionsTargetModifiers::UnstableOptions( + UnstableOptionsTargetModifiers::Sanitizer, + ) => { + collected_options + .target_modifiers + .entry(tmod) + .and_modify(|existing| { + existing.push(','); + existing.push_str(&v); + }) + .or_insert(v); + } + _ => { + collected_options.target_modifiers.insert(tmod, v); + } + } } if let Some(mitigation) = mitigation { collected_options.mitigations.reset_mitigation(*mitigation, index); diff --git a/tests/codegen-llvm/sanitizer/multiple-sanitizers.rs b/tests/codegen-llvm/sanitizer/multiple-sanitizers.rs new file mode 100644 index 0000000000000..862999e7ac026 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/multiple-sanitizers.rs @@ -0,0 +1,18 @@ +// Verifies that multiple compatible sanitizers (CFI + SafeStack) can be enabled together +// and their target modifiers accumulate instead of overwriting. +// +//@ only-x86_64 +//@ only-linux +//@ needs-sanitizer-cfi +//@ needs-sanitizer-safestack +//@ compile-flags: -Zsanitizer=cfi -Zsanitizer=safestack -Clto -Ccodegen-units=1 -C unsafe-allow-abi-mismatch=sanitizer + +#![crate_type = "lib"] + +// CHECK: ; Function Attrs:{{.*}}safestack +// CHECK: define{{.*}}foo{{.*}}!type +pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { + f(arg) +} + +// CHECK: attributes #0 = {{.*}}safestack{{.*}} diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr index 440a91c7707f8..44a2c24b2324e 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr @@ -1,5 +1,5 @@ error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` - --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + --> $DIR/sanitizers-safestack-and-kcfi.rs:18:1 | LL | #![feature(no_core)] | ^ diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr index 6cdd7facc3781..e951b36969b78 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr @@ -1,5 +1,5 @@ error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` - --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + --> $DIR/sanitizers-safestack-and-kcfi.rs:18:1 | LL | #![feature(no_core)] | ^ diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr index ecfbcace39fe5..9fd2738ef45ab 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr @@ -1,5 +1,5 @@ error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` - --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + --> $DIR/sanitizers-safestack-and-kcfi.rs:18:1 | LL | #![feature(no_core)] | ^ diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs index 6c3ceb7e91008..eb4b4d6194228 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs @@ -4,14 +4,16 @@ //@ aux-build:safestack-and-kcfi.rs //@ compile-flags: -Cpanic=abort -//@ revisions: good good_reverted missed_safestack missed_kcfi missed_both +//@ revisions: good good_reverted good_multiple missed_safestack missed_kcfi missed_both //@[good] compile-flags: -Zsanitizer=safestack,kcfi //@[good_reverted] compile-flags: -Zsanitizer=kcfi,safestack +//@[good_multiple] compile-flags: -Zsanitizer=safestack -Zsanitizer=kcfi //@[missed_safestack] compile-flags: -Zsanitizer=kcfi //@[missed_kcfi] compile-flags: -Zsanitizer=safestack // [missed_both] no additional compile-flags: //@[good] check-pass //@[good_reverted] check-pass +//@[good_multiple] check-pass #![feature(no_core)] //[missed_safestack]~^ ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi`