From 693e22fe0993abb7aea99565568986ca82b8f9ae Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Wed, 10 Jun 2026 15:49:36 +0000 Subject: [PATCH 1/4] sanitizers: Implement support for the sanitize ignorelist The sanitize ignorelist gives central controls over which functions, files, etc. should be ignored and not sanitized. It is a common file format for clang and explained here: https://clang.llvm.org/docs/SanitizerSpecialCaseList.html. This change adds support for this list in Rust as well. --- compiler/rustc_codegen_llvm/src/abi.rs | 1 + compiler/rustc_codegen_llvm/src/allocator.rs | 2 +- compiler/rustc_codegen_llvm/src/attributes.rs | 65 +++++++++++++- compiler/rustc_codegen_llvm/src/base.rs | 7 +- compiler/rustc_codegen_llvm/src/builder.rs | 88 ++++++++++++++----- compiler/rustc_codegen_llvm/src/consts.rs | 46 ++++++++++ compiler/rustc_codegen_llvm/src/context.rs | 22 +++++ compiler/rustc_codegen_llvm/src/declare.rs | 55 ++++++++++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 15 +++- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 46 ++++++++++ .../rustc_llvm/llvm-wrapper/LLVMWrapper.h | 1 + .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 34 +++++++ compiler/rustc_session/src/options.rs | 2 + .../codegen-llvm/sanitizer/cfi-ignorelist.rs | 22 +++++ .../sanitizer/global-ignorelist.rs | 13 +++ .../sanitizer/global-ignorelist.txt | 3 + tests/codegen-llvm/sanitizer/ignorelist.rs | 74 ++++++++++++++++ tests/codegen-llvm/sanitizer/ignorelist.txt | 38 ++++++++ .../codegen-llvm/sanitizer/kcfi-ignorelist.rs | 18 ++++ .../sanitizer/kernel-address-ignorelist.rs | 20 +++++ .../sanitizer/kernel-address-ignorelist.txt | 5 ++ .../codegen-llvm/sanitizer/mainfile-ignore.rs | 12 +++ .../sanitizer/mainfile-ignorelist.txt | 2 + .../sanitizer/override-ignorelist.rs | 20 +++++ .../sanitizer/override-ignorelist.txt | 3 + .../sanitizer/src-ignore-memory.rs | 74 ++++++++++++++++ tests/codegen-llvm/sanitizer/src-ignore.rs | 13 +++ .../sanitizer/type-ignorelist-asan.rs | 21 +++++ .../sanitizer/type-ignorelist-kcfi.rs | 18 ++++ .../codegen-llvm/sanitizer/type-ignorelist.rs | 20 +++++ .../type-string-unsafe-ignorelist.txt | 2 + .../sanitizer/type-string-unsafe.rs | 10 +++ 32 files changed, 734 insertions(+), 38 deletions(-) create mode 100644 tests/codegen-llvm/sanitizer/cfi-ignorelist.rs create mode 100644 tests/codegen-llvm/sanitizer/global-ignorelist.rs create mode 100644 tests/codegen-llvm/sanitizer/global-ignorelist.txt create mode 100644 tests/codegen-llvm/sanitizer/ignorelist.rs create mode 100644 tests/codegen-llvm/sanitizer/ignorelist.txt create mode 100644 tests/codegen-llvm/sanitizer/kcfi-ignorelist.rs create mode 100644 tests/codegen-llvm/sanitizer/kernel-address-ignorelist.rs create mode 100644 tests/codegen-llvm/sanitizer/kernel-address-ignorelist.txt create mode 100644 tests/codegen-llvm/sanitizer/mainfile-ignore.rs create mode 100644 tests/codegen-llvm/sanitizer/mainfile-ignorelist.txt create mode 100644 tests/codegen-llvm/sanitizer/override-ignorelist.rs create mode 100644 tests/codegen-llvm/sanitizer/override-ignorelist.txt create mode 100644 tests/codegen-llvm/sanitizer/src-ignore-memory.rs create mode 100644 tests/codegen-llvm/sanitizer/src-ignore.rs create mode 100644 tests/codegen-llvm/sanitizer/type-ignorelist-asan.rs create mode 100644 tests/codegen-llvm/sanitizer/type-ignorelist-kcfi.rs create mode 100644 tests/codegen-llvm/sanitizer/type-ignorelist.rs create mode 100644 tests/codegen-llvm/sanitizer/type-string-unsafe-ignorelist.txt create mode 100644 tests/codegen-llvm/sanitizer/type-string-unsafe.rs diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 4d18818bbe7bd..3223d3f73bdc2 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -595,6 +595,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { llfn, &cx.tcx.codegen_instance_attrs(instance.def), Some(instance), + cx.sanitizer_ignorelist.as_ref(), ); } } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 9bace9d2acf61..bf4ad2522fb7d 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -125,7 +125,7 @@ fn create_wrapper_function( ty, ); - llfn_attrs_from_instance(cx, tcx, llfn, attrs, None); + llfn_attrs_from_instance(cx, tcx, llfn, attrs, None, None); let no_return = if no_return { // -> ! DIFlagNoReturn diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 6295d05f5d508..55ba4fe138b17 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -111,9 +111,9 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( cx: &SimpleCx<'ll>, tcx: TyCtxt<'tcx>, sanitizer_fn_attr: SanitizerFnAttrs, + enabled: SanitizerSet, ) -> SmallVec<[&'ll Attribute; 4]> { let mut attrs = SmallVec::new(); - let enabled = tcx.sess.sanitizers() - sanitizer_fn_attr.disabled; if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) { attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx)); } @@ -409,6 +409,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( llfn: &'ll Value, codegen_fn_attrs: &CodegenFnAttrs, instance: Option>, + sanitizer_ignorelist: Option<&crate::llvm::SanitizerIgnoreList>, ) { let sess = tcx.sess; let mut to_add = SmallVec::<[_; 16]>::new(); @@ -470,7 +471,67 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( // not used. } else { // Do not set sanitizer attributes for naked functions. - to_add.extend(sanitize_attrs(cx, tcx, codegen_fn_attrs.sanitizers)); + let mut enabled = tcx.sess.sanitizers() - codegen_fn_attrs.sanitizers.disabled; + if let Some(ignorelist) = sanitizer_ignorelist { + if let Some(instance) = instance { + let sym_name = tcx.symbol_name(instance).name; + let span = tcx.def_span(instance.def_id()); + let source_map = tcx.sess.source_map(); + let filename = + source_map.span_to_filename(span).prefer_local_unconditionally().to_string(); + + let mainfile = tcx + .sess + .local_crate_source_file() + .and_then(|path| path.local_path().map(|p| p.display().to_string())) + .unwrap_or_default(); + + let demangled = rustc_middle::ty::print::with_no_trimmed_paths!( + tcx.def_path_str(instance.def_id()) + ); + let is_ignored = |section: &std::ffi::CStr| -> bool { + ignorelist.contains_prefix(section, c"fun", sym_name) + || ignorelist.contains_prefix(section, c"fun", &demangled) + || ignorelist.contains_prefix(section, c"src", &filename) + || (!mainfile.is_empty() + && ignorelist.contains_prefix(section, c"mainfile", &mainfile)) + }; + + let ignore_address = is_ignored(c"address"); + let ignore_kernel_address = ignore_address || is_ignored(c"kernel-address"); + let ignore_hwaddress = is_ignored(c"hwaddress"); + let ignore_kernel_hwaddress = ignore_hwaddress || is_ignored(c"kernel-hwaddress"); + + if enabled.contains(SanitizerSet::ADDRESS) && ignore_address { + enabled.remove(SanitizerSet::ADDRESS); + } + if enabled.contains(SanitizerSet::KERNELADDRESS) && ignore_kernel_address { + enabled.remove(SanitizerSet::KERNELADDRESS); + } + if enabled.contains(SanitizerSet::MEMORY) && is_ignored(c"memory") { + enabled.remove(SanitizerSet::MEMORY); + } + if enabled.contains(SanitizerSet::THREAD) && is_ignored(c"thread") { + enabled.remove(SanitizerSet::THREAD); + } + if enabled.contains(SanitizerSet::HWADDRESS) && ignore_hwaddress { + enabled.remove(SanitizerSet::HWADDRESS); + } + if enabled.contains(SanitizerSet::KERNELHWADDRESS) && ignore_kernel_hwaddress { + enabled.remove(SanitizerSet::KERNELHWADDRESS); + } + if enabled.contains(SanitizerSet::SAFESTACK) && is_ignored(c"safestack") { + enabled.remove(SanitizerSet::SAFESTACK); + } + if is_ignored(c"cfi") { + to_add.push(llvm::CreateAttrString(cx.llcx, "no-sanitize-cfi")); + } + if is_ignored(c"kcfi") { + to_add.push(llvm::CreateAttrString(cx.llcx, "no-sanitize-kcfi")); + } + } + } + to_add.extend(sanitize_attrs(cx, tcx, codegen_fn_attrs.sanitizers, enabled)); // For non-naked functions, set branch protection attributes on aarch64. if let Some(BranchProtection { bti, pac_ret, gcs }) = diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index a7dec13422f46..00fda6a2d54c8 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -123,7 +123,12 @@ pub(crate) fn compile_codegen_unit( if let Some(entry) = maybe_create_entry_wrapper::>(&cx, cx.codegen_unit) { - let attrs = attributes::sanitize_attrs(&cx, tcx, SanitizerFnAttrs::default()); + let attrs = attributes::sanitize_attrs( + &cx, + tcx, + SanitizerFnAttrs::default(), + tcx.sess.sanitizers(), + ); attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 134bc5006dd00..62ade71878195 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1832,7 +1832,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // Emit KCFI operand bundle let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn); - if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) { + if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|bundle| bundle.as_ref()) { bundles.push(kcfi_bundle); } @@ -1875,6 +1875,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { { return; } + if crate::llvm::HasStringAttribute(self.llfn(), "no-sanitize-cfi") { + return; + } let mut options = cfi::TypeIdOptions::empty(); if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() { @@ -1884,11 +1887,29 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { options.insert(cfi::TypeIdOptions::NORMALIZE_INTEGERS); } + let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); + let output = fn_abi.ret.layout.ty; + let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); + fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); + fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); + let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); + let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); + let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + let typeid = if let Some(instance) = instance { cfi::typeid_for_instance(self.tcx, instance, options) } else { cfi::typeid_for_fnabi(self.tcx, fn_abi, options) }; + + if self + .cx + .sanitizer_ignorelist + .as_ref() + .is_some_and(|ignorelist| ignorelist.contains_prefix(c"cfi", c"type", &type_name)) + { + return; + } let typeid_metadata = self.cx.create_metadata(typeid.as_bytes()); let dbg_loc = self.get_dbg_loc(); @@ -1924,34 +1945,53 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { llfn: &'ll Value, ) -> Option> { let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) }; - let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled() - && let Some(fn_abi) = fn_abi - && is_indirect_call - { - if let Some(fn_attrs) = fn_attrs - && fn_attrs.sanitizers.disabled.contains(SanitizerSet::KCFI) + let kcfi_bundle = + if self.tcx.sess.is_sanitizer_kcfi_enabled() + && let Some(fn_abi) = fn_abi + && is_indirect_call { - return None; - } + if let Some(fn_attrs) = fn_attrs + && fn_attrs.sanitizers.disabled.contains(SanitizerSet::KCFI) + { + return None; + } + if crate::llvm::HasStringAttribute(self.llfn(), "no-sanitize-kcfi") { + return None; + } - let mut options = kcfi::TypeIdOptions::empty(); - if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() { - options.insert(kcfi::TypeIdOptions::GENERALIZE_POINTERS); - } - if self.tcx.sess.is_sanitizer_cfi_normalize_integers_enabled() { - options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); - } + let mut options = kcfi::TypeIdOptions::empty(); + if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() { + options.insert(kcfi::TypeIdOptions::GENERALIZE_POINTERS); + } + if self.tcx.sess.is_sanitizer_cfi_normalize_integers_enabled() { + options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); + } + + let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); + let output = fn_abi.ret.layout.ty; + let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); + fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); + fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); + let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); + let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); + let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + + if self.cx.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { + ignorelist.contains_prefix(c"kcfi", c"type", &type_name) + }) { + return None; + } + + let kcfi_typeid = if let Some(instance) = instance { + kcfi::typeid_for_instance(self.tcx, instance, options) + } else { + kcfi::typeid_for_fnabi(self.tcx, fn_abi, options) + }; - let kcfi_typeid = if let Some(instance) = instance { - kcfi::typeid_for_instance(self.tcx, instance, options) + Some(llvm::OperandBundleBox::new("kcfi", &[self.const_u32(kcfi_typeid)])) } else { - kcfi::typeid_for_fnabi(self.tcx, fn_abi, options) + None }; - - Some(llvm::OperandBundleBox::new("kcfi", &[self.const_u32(kcfi_typeid)])) - } else { - None - }; kcfi_bundle } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index ab3e4b8d9effa..973a25edc9e2f 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -509,6 +509,52 @@ impl<'ll> CodegenCx<'ll, '_> { base::set_variable_sanitizer_attrs(g, attrs); + if let Some(ignorelist) = &self.sanitizer_ignorelist { + let instance = ty::Instance::mono(self.tcx, def_id); + let sym_name = self.tcx.symbol_name(instance).name; + let span = self.tcx.def_span(def_id); + let source_map = self.tcx.sess.source_map(); + let filename = + source_map.span_to_filename(span).prefer_local_unconditionally().to_string(); + let ty_name = rustc_middle::ty::print::with_no_trimmed_paths!( + self.tcx.type_of(def_id).skip_binder().to_string() + ); + let mainfile = self + .tcx + .sess + .local_crate_source_file() + .and_then(|path| path.local_path().map(|p| p.display().to_string())) + .unwrap_or_default(); + + let is_ignored = |section: &std::ffi::CStr| -> bool { + ignorelist.contains_prefix(section, c"global", sym_name) + || ignorelist.contains_prefix(section, c"src", &filename) + || (!mainfile.is_empty() + && ignorelist.contains_prefix(section, c"mainfile", &mainfile)) + || ignorelist.contains_prefix(section, c"type", &ty_name) + }; + + let sanitizers = self.tcx.sess.sanitizers(); + let ignore_address = is_ignored(c"address"); + let ignore_kernel_address = ignore_address || is_ignored(c"kernel-address"); + let ignore_hwaddress = is_ignored(c"hwaddress"); + let ignore_kernel_hwaddress = ignore_hwaddress || is_ignored(c"kernel-hwaddress"); + + if (sanitizers.contains(rustc_target::spec::SanitizerSet::ADDRESS) && ignore_address) + || (sanitizers.contains(rustc_target::spec::SanitizerSet::KERNELADDRESS) + && ignore_kernel_address) + { + unsafe { llvm::LLVMRustSetNoSanitizeAddress(g) }; + } + if (sanitizers.contains(rustc_target::spec::SanitizerSet::HWADDRESS) + && ignore_hwaddress) + || (sanitizers.contains(rustc_target::spec::SanitizerSet::KERNELHWADDRESS) + && ignore_kernel_hwaddress) + { + unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(g) }; + } + } + if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { // `USED` and `USED_LINKER` can't be used together. assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 85a7f9cab73a4..2d632648b5b0f 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -133,6 +133,7 @@ pub(crate) struct FullCx<'ll, 'tcx> { /// Extra per-CGU codegen state needed when coverage instrumentation is enabled. pub coverage_cx: Option>, pub dbg_cx: Option>, + pub sanitizer_ignorelist: Option, eh_personality: Cell>, pub rust_try_fn: Cell>, @@ -650,6 +651,26 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { None }; + // FIXME: This parses the ignorelist files for each CGU, which adds a performance overhead. + // Clang parses it once per frontend invocation. LLVM's `SpecialCaseList::inSection` + // mutates an internal `LazyInit` cache and is not thread-safe. We either need to wrap + // the queries in a lock or wait for LLVM to expose a thread-safe way to query it. + let sanitizer_ignorelist = if !tcx.sess.opts.unstable_opts.sanitizer_ignorelist.is_empty() { + for path in &tcx.sess.opts.unstable_opts.sanitizer_ignorelist { + let _ = tcx.sess.source_map().load_file(std::path::Path::new(path)); + } + match crate::llvm::SanitizerIgnoreList::new( + &tcx.sess.opts.unstable_opts.sanitizer_ignorelist, + ) { + Ok(list) => Some(list), + Err(err) => { + tcx.dcx().fatal(format!("failed to parse sanitizer ignorelist: {}", err)); + } + } + } else { + None + }; + GenericCx( FullCx { tcx, @@ -669,6 +690,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { scalar_lltypes: Default::default(), coverage_cx, dbg_cx, + sanitizer_ignorelist, eh_personality: Cell::new(None), rust_try_fn: Cell::new(None), intrinsics: Default::default(), diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 419d38f95e595..2636da108315b 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -190,7 +190,18 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { ); fn_abi.apply_attrs_llfn(self, llfn, instance); - if self.tcx.sess.is_sanitizer_cfi_enabled() { + if self.tcx.sess.is_sanitizer_cfi_enabled() + && !crate::llvm::HasStringAttribute(llfn, "no-sanitize-cfi") + { + let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); + let output = fn_abi.ret.layout.ty; + let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); + fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); + fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); + let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); + let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); + let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + if let Some(instance) = instance { let mut typeids = FxIndexSet::default(); for options in [ @@ -203,7 +214,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { .map(cfi::TypeIdOptions::from_iter) { let typeid = cfi::typeid_for_instance(self.tcx, instance, options); - if typeids.insert(typeid.clone()) { + let ignored = self.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { + ignorelist.contains_prefix(c"cfi", c"type", &type_name) + }); + if !ignored && typeids.insert(typeid.clone()) { self.add_type_metadata(llfn, typeid.as_bytes()); } } @@ -217,12 +231,20 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { .map(cfi::TypeIdOptions::from_iter) { let typeid = cfi::typeid_for_fnabi(self.tcx, fn_abi, options); - self.add_type_metadata(llfn, typeid.as_bytes()); + let ignored = self + .sanitizer_ignorelist + .as_ref() + .is_some_and(|l| l.contains_prefix(c"cfi", c"type", &type_name)); + if !ignored { + self.add_type_metadata(llfn, typeid.as_bytes()); + } } } } - if self.tcx.sess.is_sanitizer_kcfi_enabled() { + if self.tcx.sess.is_sanitizer_kcfi_enabled() + && !crate::llvm::HasStringAttribute(llfn, "no-sanitize-kcfi") + { // LLVM KCFI does not support multiple !kcfi_type attachments let mut options = kcfi::TypeIdOptions::empty(); if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() { @@ -232,11 +254,26 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); } - if let Some(instance) = instance { - let kcfi_typeid = kcfi::typeid_for_instance(self.tcx, instance, options); - self.set_kcfi_type_metadata(llfn, kcfi_typeid); - } else { - let kcfi_typeid = kcfi::typeid_for_fnabi(self.tcx, fn_abi, options); + let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); + let output = fn_abi.ret.layout.ty; + let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); + fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); + fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); + let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); + let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); + let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + + let ignored = self + .sanitizer_ignorelist + .as_ref() + .is_some_and(|l| l.contains_prefix(c"kcfi", c"type", &type_name)); + + if !ignored { + let kcfi_typeid = if let Some(instance) = instance { + kcfi::typeid_for_instance(self.tcx, instance, options) + } else { + kcfi::typeid_for_fnabi(self.tcx, fn_abi, options) + }; self.set_kcfi_type_metadata(llfn, kcfi_typeid); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 919868b9005eb..4d388bcead590 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -690,7 +690,7 @@ pub(crate) enum CompressionKind { } unsafe extern "C" { - type Opaque; + pub(crate) type Opaque; } #[repr(C)] struct InvariantOpaque<'a> { @@ -2500,6 +2500,19 @@ unsafe extern "C" { pub(crate) fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); pub(crate) fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); + pub(crate) fn LLVMRustSpecialCaseListCreate( + Paths: *const *const c_char, + NumPaths: size_t, + ErrorMsg: &RustString, + ) -> *mut Opaque; + pub(crate) fn LLVMRustSpecialCaseListDestroy(List: *mut Opaque); + pub(crate) fn LLVMRustSpecialCaseListContainsPrefix( + List: *const Opaque, + Section: *const c_char, + Prefix: *const c_char, + Query: *const c_char, + ) -> bool; + pub(crate) fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); pub(crate) fn LLVMRustUnpackOptimizationDiagnostic<'a>( diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 2ec19b1795b5a..aac36e6433fa8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -358,6 +358,52 @@ pub(crate) fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec { RustString::build_byte_buffer(f) } +pub(crate) struct SanitizerIgnoreList { + inner: *mut ffi::Opaque, +} + +impl SanitizerIgnoreList { + pub(crate) fn new(paths: &[String]) -> Result { + use std::ffi::CString; + let c_paths: Vec = + paths.iter().map(|p| CString::new(p.as_str()).unwrap()).collect(); + let c_ptrs: Vec<*const libc::c_char> = c_paths.iter().map(|c| c.as_ptr()).collect(); + + let mut inner = std::ptr::null_mut(); + let err = build_string(|err| unsafe { + inner = ffi::LLVMRustSpecialCaseListCreate(c_ptrs.as_ptr(), c_ptrs.len(), err); + }); + + let err = err.unwrap_or_else(|e| format!("utf8 error: {}", e)); + if inner.is_null() { Err(err) } else { Ok(Self { inner }) } + } + + pub(crate) fn contains_prefix( + &self, + section: &std::ffi::CStr, + prefix: &std::ffi::CStr, + query: &str, + ) -> bool { + let query = std::ffi::CString::new(query).unwrap(); + unsafe { + ffi::LLVMRustSpecialCaseListContainsPrefix( + self.inner, + section.as_ptr(), + prefix.as_ptr(), + query.as_ptr(), + ) + } + } +} + +impl Drop for SanitizerIgnoreList { + fn drop(&mut self) { + unsafe { + ffi::LLVMRustSpecialCaseListDestroy(self.inner); + } + } +} + pub(crate) fn twine_to_string(tr: &Twine) -> String { unsafe { build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM") diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 0cbda23f384cc..ba8d00648425d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -21,6 +21,7 @@ enum class LLVMRustResult { Success, Failure }; typedef struct OpaqueRustString *RustStringRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef; +typedef struct LLVMOpaqueSpecialCaseList *LLVMSpecialCaseListRef; extern "C" void LLVMRustStringWriteImpl(RustStringRef buf, const char *slice_ptr, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index a50b06e5120b2..a5b9ccd528219 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -34,8 +34,10 @@ #include "llvm/Support/JSON.h" #include "llvm/Support/ModRef.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/Timer.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include @@ -1895,3 +1897,35 @@ FIXED_MD_KIND(MD_noalias_addrspace, 41) // LLVM versions, it's fine to omit them from this list; in that case Rust-side // code cannot declare them as fixed IDs and must look them up by name instead. #undef FIXED_MD_KIND + +extern "C" LLVMSpecialCaseListRef +LLVMRustSpecialCaseListCreate(const char **Paths, size_t NumPaths, + RustStringRef ErrorMsg) { + std::string Error; + std::vector PathsVec(Paths, Paths + NumPaths); + std::unique_ptr SCL = llvm::SpecialCaseList::create( + PathsVec, *llvm::vfs::getRealFileSystem(), Error); + if (!SCL) { + LLVMRustStringWriteImpl(ErrorMsg, Error.data(), Error.size()); + return nullptr; + } + return reinterpret_cast(SCL.release()); +} + +extern "C" void LLVMRustSpecialCaseListDestroy(LLVMSpecialCaseListRef List) { + delete reinterpret_cast(List); +} + +extern "C" bool +LLVMRustSpecialCaseListContainsPrefix(LLVMSpecialCaseListRef List, + const char *Section, const char *Prefix, + const char *Query) { + auto *SCL = reinterpret_cast(List); + std::pair NoSan = + SCL->inSectionBlame(Section, Prefix, Query); + if (NoSan.second == 0) + return false; + std::pair San = + SCL->inSectionBlame(Section, Prefix, Query, "sanitize"); + return San.second == 0 || NoSan > San; +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6ae0d9721bc00..de4365e13f119 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2620,6 +2620,8 @@ written to standard error output)"), #[rustc_lint_opt_deny_field_access("use `Session::sanitizers()` instead of this field")] sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED] { TARGET_MODIFIER: Sanitizer }, "use a sanitizer"), + sanitizer_ignorelist: Vec = (vec![], parse_list, [TRACKED], + "list of files providing ignorelists for sanitizers"), sanitizer_cfi_canonical_jump_tables: Option = (Some(true), parse_opt_bool, [TRACKED], "enable canonical jump tables (default: yes)"), sanitizer_cfi_generalize_pointers: Option = (None, parse_opt_bool, [TRACKED], diff --git a/tests/codegen-llvm/sanitizer/cfi-ignorelist.rs b/tests/codegen-llvm/sanitizer/cfi-ignorelist.rs new file mode 100644 index 0000000000000..8871e7f0dcd39 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/cfi-ignorelist.rs @@ -0,0 +1,22 @@ +//@ needs-sanitizer-cfi +//@ compile-flags: -Zsanitizer=cfi -Clto -Cunsafe-allow-abi-mismatch=sanitizer -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: define void @test_cfi +// CHECK-NOT: !type +#[no_mangle] +pub fn test_cfi(f: fn(), x: &mut i32) { + *x = 1; + // CHECK-NOT: trap + f(); +} + +// CHECK: define void @test_memory +// CHECK-SAME: !type +#[no_mangle] +pub fn test_memory(f: fn(i32), x: &mut i32) { + *x = 2; + // CHECK: trap + f(1); +} diff --git a/tests/codegen-llvm/sanitizer/global-ignorelist.rs b/tests/codegen-llvm/sanitizer/global-ignorelist.rs new file mode 100644 index 0000000000000..994dccd834f1c --- /dev/null +++ b/tests/codegen-llvm/sanitizer/global-ignorelist.rs @@ -0,0 +1,13 @@ +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Zsanitizer-ignorelist={{src-base}}/sanitizer/global-ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: @IGNORED_GLOBAL = {{.*}} no_sanitize_address +#[no_mangle] +pub static IGNORED_GLOBAL: i64 = 42; + +// CHECK: @CHECKED_GLOBAL = {{.*}} no_sanitize_address +// (because of src:*global-ignorelist.rs) +#[no_mangle] +pub static CHECKED_GLOBAL: i64 = 42; diff --git a/tests/codegen-llvm/sanitizer/global-ignorelist.txt b/tests/codegen-llvm/sanitizer/global-ignorelist.txt new file mode 100644 index 0000000000000..b82472fb39422 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/global-ignorelist.txt @@ -0,0 +1,3 @@ +[address] +global:*IGNORED_GLOBAL* +src:*global-ignorelist.rs diff --git a/tests/codegen-llvm/sanitizer/ignorelist.rs b/tests/codegen-llvm/sanitizer/ignorelist.rs new file mode 100644 index 0000000000000..d71a17b4b3c1b --- /dev/null +++ b/tests/codegen-llvm/sanitizer/ignorelist.rs @@ -0,0 +1,74 @@ +//@ revisions: ASAN MSAN TSAN HWASAN SAFESTACK +//@[ASAN] needs-sanitizer-address +//@[MSAN] needs-sanitizer-memory +//@[TSAN] needs-sanitizer-thread +//@[HWASAN] needs-sanitizer-hwaddress +//@[SAFESTACK] needs-sanitizer-safestack +//@ compile-flags: -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt -Cunsafe-allow-abi-mismatch=sanitizer +//@ [ASAN] compile-flags: -Zsanitizer=address +//@ [MSAN] compile-flags: -Zsanitizer=memory +//@ [TSAN] compile-flags: -Zsanitizer=thread +//@ [HWASAN] compile-flags: -Zsanitizer=hwaddress -C target-feature=+tagged-globals +//@ [SAFESTACK] compile-flags: -Zsanitizer=safestack + +#![crate_type = "lib"] + +// CHECK: ; Function Attrs: +// ASAN-NOT: sanitize_address +// MSAN-SAME: sanitize_memory +// TSAN-SAME: sanitize_thread +// HWASAN-SAME: sanitize_hwaddress +// SAFESTACK-SAME: safestack +// CHECK-NEXT: define void @test_address +#[no_mangle] +pub fn test_address(x: &mut i32) { + *x = 1; +} + +// CHECK: ; Function Attrs: +// ASAN-SAME: sanitize_address +// MSAN-NOT: sanitize_memory +// TSAN-SAME: sanitize_thread +// HWASAN-SAME: sanitize_hwaddress +// SAFESTACK-SAME: safestack +// CHECK-NEXT: define void @test_memory +#[no_mangle] +pub fn test_memory(x: &mut i32) { + *x = 2; +} + +// CHECK: ; Function Attrs: +// ASAN-SAME: sanitize_address +// MSAN-SAME: sanitize_memory +// TSAN-NOT: sanitize_thread +// HWASAN-SAME: sanitize_hwaddress +// SAFESTACK-SAME: safestack +// CHECK-NEXT: define void @test_thread +#[no_mangle] +pub fn test_thread(x: &mut i32) { + *x = 3; +} + +// CHECK: ; Function Attrs: +// ASAN-SAME: sanitize_address +// MSAN-SAME: sanitize_memory +// TSAN-SAME: sanitize_thread +// HWASAN-NOT: sanitize_hwaddress +// SAFESTACK-SAME: safestack +// CHECK-NEXT: define void @test_hwaddress +#[no_mangle] +pub fn test_hwaddress(x: &mut i32) { + *x = 4; +} + +// CHECK: ; Function Attrs: +// ASAN-SAME: sanitize_address +// MSAN-SAME: sanitize_memory +// TSAN-SAME: sanitize_thread +// HWASAN-SAME: sanitize_hwaddress +// SAFESTACK-NOT: safestack +// CHECK-NEXT: define void @test_safestack +#[no_mangle] +pub fn test_safestack(x: &mut i32) { + *x = 5; +} diff --git a/tests/codegen-llvm/sanitizer/ignorelist.txt b/tests/codegen-llvm/sanitizer/ignorelist.txt new file mode 100644 index 0000000000000..16c9b8b284714 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/ignorelist.txt @@ -0,0 +1,38 @@ +[address] +fun:*test_address* +src:*src-ignore-memory.rs + +[memory] +fun:*test_memory* +src:*src-ignore-memory.rs + +[thread] +fun:*test_thread* +src:*src-ignore-memory.rs + +[hwaddress] +fun:*test_hwaddress* +src:*src-ignore-memory.rs + +[safestack] +fun:*test_safestack* +src:*src-ignore-memory.rs + +[cfi] +fun:*test_cfi* +src:*src-ignore* +type:fn() + +[kcfi] +fun:*test_kcfi* +src:*src-ignore* +type:fn() + +[address] +type:i32 + +[hwaddress] +type:i32 + +[address] +type:MyStruct diff --git a/tests/codegen-llvm/sanitizer/kcfi-ignorelist.rs b/tests/codegen-llvm/sanitizer/kcfi-ignorelist.rs new file mode 100644 index 0000000000000..207a561714b78 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/kcfi-ignorelist.rs @@ -0,0 +1,18 @@ +//@ needs-sanitizer-kcfi +//@ compile-flags: -Zsanitizer=kcfi -C panic=abort -Cunsafe-allow-abi-mismatch=sanitizer -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: define void @test_kcfi +// CHECK-NOT: !kcfi_type +#[no_mangle] +pub fn test_kcfi(x: &mut i32) { + *x = 1; +} + +// CHECK: define void @test_memory +// CHECK-SAME: !kcfi_type +#[no_mangle] +pub fn test_memory(x: &mut i32) { + *x = 2; +} diff --git a/tests/codegen-llvm/sanitizer/kernel-address-ignorelist.rs b/tests/codegen-llvm/sanitizer/kernel-address-ignorelist.rs new file mode 100644 index 0000000000000..c6a59365f1671 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/kernel-address-ignorelist.rs @@ -0,0 +1,20 @@ +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Zsanitizer-ignorelist={{src-base}}/sanitizer/kernel-address-ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: ; Function Attrs: +// CHECK-SAME: sanitize_address +// CHECK-NEXT: define void @test_kernel_address_ignored +#[no_mangle] +pub fn test_kernel_address_ignored(x: &mut i32) { + *x = 1; +} + +// CHECK: ; Function Attrs: +// CHECK-NOT: sanitize_address +// CHECK-NEXT: define void @test_address_ignored +#[no_mangle] +pub fn test_address_ignored(x: &mut i32) { + *x = 2; +} diff --git a/tests/codegen-llvm/sanitizer/kernel-address-ignorelist.txt b/tests/codegen-llvm/sanitizer/kernel-address-ignorelist.txt new file mode 100644 index 0000000000000..c21e081a1057f --- /dev/null +++ b/tests/codegen-llvm/sanitizer/kernel-address-ignorelist.txt @@ -0,0 +1,5 @@ +[kernel-address] +fun:test_kernel_address_ignored + +[address] +fun:test_address_ignored diff --git a/tests/codegen-llvm/sanitizer/mainfile-ignore.rs b/tests/codegen-llvm/sanitizer/mainfile-ignore.rs new file mode 100644 index 0000000000000..683f739c53be2 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/mainfile-ignore.rs @@ -0,0 +1,12 @@ +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Zsanitizer-ignorelist={{src-base}}/sanitizer/mainfile-ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: ; Function Attrs: +// CHECK-NOT: sanitize_address +// CHECK-NEXT: define void @test_mainfile +#[no_mangle] +pub fn test_mainfile(x: &mut i32) { + *x = 1; +} diff --git a/tests/codegen-llvm/sanitizer/mainfile-ignorelist.txt b/tests/codegen-llvm/sanitizer/mainfile-ignorelist.txt new file mode 100644 index 0000000000000..e446cec256466 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/mainfile-ignorelist.txt @@ -0,0 +1,2 @@ +[address] +mainfile:*mainfile-ignore.rs diff --git a/tests/codegen-llvm/sanitizer/override-ignorelist.rs b/tests/codegen-llvm/sanitizer/override-ignorelist.rs new file mode 100644 index 0000000000000..74743cfc27358 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/override-ignorelist.rs @@ -0,0 +1,20 @@ +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Zsanitizer-ignorelist={{src-base}}/sanitizer/override-ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: ; Function Attrs: +// CHECK-NOT: sanitize_address +// CHECK-NEXT: define void @test_ignored +#[no_mangle] +pub fn test_ignored(x: &mut i32) { + *x = 1; +} + +// CHECK: ; Function Attrs: +// CHECK-SAME: sanitize_address +// CHECK-NEXT: define void @test_re_enabled +#[no_mangle] +pub fn test_re_enabled(x: &mut i32) { + *x = 2; +} diff --git a/tests/codegen-llvm/sanitizer/override-ignorelist.txt b/tests/codegen-llvm/sanitizer/override-ignorelist.txt new file mode 100644 index 0000000000000..77d66c8341bce --- /dev/null +++ b/tests/codegen-llvm/sanitizer/override-ignorelist.txt @@ -0,0 +1,3 @@ +[address] +fun:* +fun:test_re_enabled=sanitize diff --git a/tests/codegen-llvm/sanitizer/src-ignore-memory.rs b/tests/codegen-llvm/sanitizer/src-ignore-memory.rs new file mode 100644 index 0000000000000..9799e9b522f03 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/src-ignore-memory.rs @@ -0,0 +1,74 @@ +//@ revisions: ASAN MSAN TSAN HWASAN SAFESTACK +//@[ASAN] needs-sanitizer-address +//@[MSAN] needs-sanitizer-memory +//@[TSAN] needs-sanitizer-thread +//@[HWASAN] needs-sanitizer-hwaddress +//@[SAFESTACK] needs-sanitizer-safestack +//@ compile-flags: -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt -Cunsafe-allow-abi-mismatch=sanitizer +//@ [ASAN] compile-flags: -Zsanitizer=address +//@ [MSAN] compile-flags: -Zsanitizer=memory +//@ [TSAN] compile-flags: -Zsanitizer=thread +//@ [HWASAN] compile-flags: -Zsanitizer=hwaddress -C target-feature=+tagged-globals +//@ [SAFESTACK] compile-flags: -Zsanitizer=safestack + +#![crate_type = "lib"] + +// CHECK: ; Function Attrs: +// ASAN-NOT: sanitize_address +// MSAN-NOT: sanitize_memory +// TSAN-NOT: sanitize_thread +// HWASAN-NOT: sanitize_hwaddress +// SAFESTACK-NOT: safestack +// CHECK-NEXT: define void @test_file_address +#[no_mangle] +pub fn test_file_address(x: &mut i32) { + *x = 1; +} + +// CHECK: ; Function Attrs: +// ASAN-NOT: sanitize_address +// MSAN-NOT: sanitize_memory +// TSAN-NOT: sanitize_thread +// HWASAN-NOT: sanitize_hwaddress +// SAFESTACK-NOT: safestack +// CHECK-NEXT: define void @test_file_memory +#[no_mangle] +pub fn test_file_memory(x: &mut i32) { + *x = 2; +} + +// CHECK: ; Function Attrs: +// ASAN-NOT: sanitize_address +// MSAN-NOT: sanitize_memory +// TSAN-NOT: sanitize_thread +// HWASAN-NOT: sanitize_hwaddress +// SAFESTACK-NOT: safestack +// CHECK-NEXT: define void @test_file_thread +#[no_mangle] +pub fn test_file_thread(x: &mut i32) { + *x = 3; +} + +// CHECK: ; Function Attrs: +// ASAN-NOT: sanitize_address +// MSAN-NOT: sanitize_memory +// TSAN-NOT: sanitize_thread +// HWASAN-NOT: sanitize_hwaddress +// SAFESTACK-NOT: safestack +// CHECK-NEXT: define void @test_file_hwaddress +#[no_mangle] +pub fn test_file_hwaddress(x: &mut i32) { + *x = 4; +} + +// CHECK: ; Function Attrs: +// ASAN-NOT: sanitize_address +// MSAN-NOT: sanitize_memory +// TSAN-NOT: sanitize_thread +// HWASAN-NOT: sanitize_hwaddress +// SAFESTACK-NOT: safestack +// CHECK-NEXT: define void @test_file_safestack +#[no_mangle] +pub fn test_file_safestack(x: &mut i32) { + *x = 5; +} diff --git a/tests/codegen-llvm/sanitizer/src-ignore.rs b/tests/codegen-llvm/sanitizer/src-ignore.rs new file mode 100644 index 0000000000000..dfacb473c8ab8 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/src-ignore.rs @@ -0,0 +1,13 @@ +//@ needs-sanitizer-cfi +//@ compile-flags: -Zsanitizer=cfi -Clto -Cunsafe-allow-abi-mismatch=sanitizer -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: define void @test_file +// CHECK-NOT: !type +#[no_mangle] +pub fn test_file(f: fn(), x: &mut i32) { + *x = 1; + // CHECK-NOT: trap + f(); +} diff --git a/tests/codegen-llvm/sanitizer/type-ignorelist-asan.rs b/tests/codegen-llvm/sanitizer/type-ignorelist-asan.rs new file mode 100644 index 0000000000000..6f04e863fb522 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/type-ignorelist-asan.rs @@ -0,0 +1,21 @@ +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: @IGNORED_GLOBAL = {{.*}} no_sanitize_address +#[no_mangle] +pub static IGNORED_GLOBAL: i32 = 42; + +// CHECK: @CHECKED_GLOBAL = +// CHECK-NOT: no_sanitize_address +#[no_mangle] +pub static CHECKED_GLOBAL: i64 = 42; + +pub struct MyStruct { + x: i32, +} + +// CHECK: @MY_STRUCT = {{.*}} no_sanitize_address +#[no_mangle] +pub static MY_STRUCT: MyStruct = MyStruct { x: 42 }; diff --git a/tests/codegen-llvm/sanitizer/type-ignorelist-kcfi.rs b/tests/codegen-llvm/sanitizer/type-ignorelist-kcfi.rs new file mode 100644 index 0000000000000..8010ce19be25a --- /dev/null +++ b/tests/codegen-llvm/sanitizer/type-ignorelist-kcfi.rs @@ -0,0 +1,18 @@ +//@ needs-sanitizer-kcfi +//@ compile-flags: -Zsanitizer=kcfi -Cpanic=abort -Cunsafe-allow-abi-mismatch=sanitizer -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: define void @test_type +// CHECK-SAME: !kcfi_type +#[no_mangle] +pub fn test_type(f: fn(), x: &mut i32) { + *x = 1; + // CHECK-NOT: !kcfi_type + f(); +} + +// CHECK: define void @test_type_2() +// CHECK-NOT: !kcfi_type +#[no_mangle] +pub fn test_type_2() {} diff --git a/tests/codegen-llvm/sanitizer/type-ignorelist.rs b/tests/codegen-llvm/sanitizer/type-ignorelist.rs new file mode 100644 index 0000000000000..6ddbb709b2d98 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/type-ignorelist.rs @@ -0,0 +1,20 @@ +//@ needs-sanitizer-cfi +//@ compile-flags: -Zsanitizer=cfi -Clto -Cunsafe-allow-abi-mismatch=sanitizer -Zsanitizer-ignorelist={{src-base}}/sanitizer/ignorelist.txt + +#![crate_type = "lib"] + +// CHECK: define void @test_type +// CHECK-SAME: !type +#[no_mangle] +pub fn test_type(f: fn(), x: &mut i32) { + *x = 1; + // CHECK-NOT: trap + f(); +} + +// Ensure the function definition of test_type_2 has no !type metadata +// since it has the type `fn()` which is ignored +// CHECK: define void @test_type_2() +// CHECK-NOT: !type +#[no_mangle] +pub fn test_type_2() {} diff --git a/tests/codegen-llvm/sanitizer/type-string-unsafe-ignorelist.txt b/tests/codegen-llvm/sanitizer/type-string-unsafe-ignorelist.txt new file mode 100644 index 0000000000000..df3db6b38ceb0 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/type-string-unsafe-ignorelist.txt @@ -0,0 +1,2 @@ +[address] +type:*unsafe*extern*fn* diff --git a/tests/codegen-llvm/sanitizer/type-string-unsafe.rs b/tests/codegen-llvm/sanitizer/type-string-unsafe.rs new file mode 100644 index 0000000000000..f4e7b83bf61b0 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/type-string-unsafe.rs @@ -0,0 +1,10 @@ +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Zsanitizer-ignorelist={{src-base}}/sanitizer/type-string-unsafe-ignorelist.txt + +#![crate_type = "lib"] + +pub static MY_FN: unsafe extern "C" fn() = my_fn_impl; + +// CHECK: MY_FN = {{.*}} no_sanitize_address + +unsafe extern "C" fn my_fn_impl() {} From dd04c725ea984d6df5c818ead795cbcd301fc568 Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Mon, 15 Jun 2026 08:35:32 +0000 Subject: [PATCH 2/4] Refactor type_name_for_ignore_list into its own method --- compiler/rustc_codegen_llvm/src/builder.rs | 20 +++----------------- compiler/rustc_codegen_llvm/src/common.rs | 16 +++++++++++++++- compiler/rustc_codegen_llvm/src/declare.rs | 20 +++----------------- 3 files changed, 21 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 62ade71878195..9750d09029077 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -31,7 +31,7 @@ use tracing::{debug, instrument}; use crate::abi::FnAbiLlvmExt; use crate::attributes; -use crate::common::Funclet; +use crate::common::{type_name_for_ignore_list, Funclet}; use crate::context::{CodegenCx, FullCx, GenericCx, SCx}; use crate::llvm::{ self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, FromGeneric, GEPNoWrapFlags, Metadata, TRUE, @@ -1887,14 +1887,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { options.insert(cfi::TypeIdOptions::NORMALIZE_INTEGERS); } - let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); - let output = fn_abi.ret.layout.ty; - let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); - fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); - fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); - let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); - let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); - let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + let type_name = type_name_for_ignore_list(self.tcx, fn_abi); let typeid = if let Some(instance) = instance { cfi::typeid_for_instance(self.tcx, instance, options) @@ -1967,14 +1960,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); } - let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); - let output = fn_abi.ret.layout.ty; - let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); - fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); - fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); - let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); - let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); - let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + let type_name = type_name_for_ignore_list(self.tcx, fn_abi); if self.cx.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { ignorelist.contains_prefix(c"kcfi", c"type", &type_name) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 5c5e9ed7e082c..9bca4d6cef55a 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -13,7 +13,7 @@ use rustc_hashes::Hash128; use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::cstore::DllImport; use tracing::debug; @@ -446,3 +446,17 @@ impl AsCCharPtr for [u8] { self.as_ptr().cast() } } + +pub(crate) fn type_name_for_ignore_list<'tcx>( + tcx: TyCtxt<'tcx>, + fn_abi: &rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, +) -> String { + let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); + let output = fn_abi.ret.layout.ty; + let mut fn_sig_kind = ty::FnSigKind::default(); + fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); + fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); + let fn_sig = tcx.mk_fn_sig(inputs, output, fn_sig_kind); + let fn_ptr = Ty::new_fn_ptr(tcx, ty::Binder::dummy(fn_sig)); + ty::print::with_no_trimmed_paths!(fn_ptr.to_string()) +} diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 2636da108315b..729fb455e33bb 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -25,7 +25,7 @@ use tracing::debug; use crate::abi::FnAbiLlvmExt; use crate::attributes; -use crate::common::AsCCharPtr; +use crate::common::{type_name_for_ignore_list, AsCCharPtr}; use crate::context::{CodegenCx, GenericCx, SCx, SimpleCx}; use crate::llvm::AttributePlace::Function; use crate::llvm::{self, FromGeneric, Type, Value, Visibility}; @@ -193,14 +193,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { if self.tcx.sess.is_sanitizer_cfi_enabled() && !crate::llvm::HasStringAttribute(llfn, "no-sanitize-cfi") { - let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); - let output = fn_abi.ret.layout.ty; - let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); - fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); - fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); - let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); - let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); - let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + let type_name = type_name_for_ignore_list(self.tcx, fn_abi); if let Some(instance) = instance { let mut typeids = FxIndexSet::default(); @@ -254,14 +247,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); } - let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect(); - let output = fn_abi.ret.layout.ty; - let mut fn_sig_kind = rustc_middle::ty::FnSigKind::default(); - fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe); - fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic); - let fn_sig = self.tcx.mk_fn_sig(inputs, output, fn_sig_kind); - let fn_ptr = Ty::new_fn_ptr(self.tcx, rustc_middle::ty::Binder::dummy(fn_sig)); - let type_name = rustc_middle::ty::print::with_no_trimmed_paths!(fn_ptr.to_string()); + let type_name = type_name_for_ignore_list(self.tcx, fn_abi); let ignored = self .sanitizer_ignorelist From 1deec8a711a9ecc1c83ed8b3e2ab4addf7829f25 Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Mon, 15 Jun 2026 08:44:43 +0000 Subject: [PATCH 3/4] Refactor when tipeid is computed --- compiler/rustc_codegen_llvm/src/builder.rs | 12 ++--- compiler/rustc_codegen_llvm/src/declare.rs | 62 ++++++++++------------ 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 9750d09029077..3b161e215618d 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1889,12 +1889,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let type_name = type_name_for_ignore_list(self.tcx, fn_abi); - let typeid = if let Some(instance) = instance { - cfi::typeid_for_instance(self.tcx, instance, options) - } else { - cfi::typeid_for_fnabi(self.tcx, fn_abi, options) - }; - if self .cx .sanitizer_ignorelist @@ -1903,6 +1897,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { { return; } + + let typeid = if let Some(instance) = instance { + cfi::typeid_for_instance(self.tcx, instance, options) + } else { + cfi::typeid_for_fnabi(self.tcx, fn_abi, options) + }; let typeid_metadata = self.cx.create_metadata(typeid.as_bytes()); let dbg_loc = self.get_dbg_loc(); diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 729fb455e33bb..a0dfbb2e79eb8 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -194,41 +194,37 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { && !crate::llvm::HasStringAttribute(llfn, "no-sanitize-cfi") { let type_name = type_name_for_ignore_list(self.tcx, fn_abi); + let ignored = self.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { + ignorelist.contains_prefix(c"cfi", c"type", &type_name) + }); - if let Some(instance) = instance { - let mut typeids = FxIndexSet::default(); - for options in [ - cfi::TypeIdOptions::GENERALIZE_POINTERS, - cfi::TypeIdOptions::NORMALIZE_INTEGERS, - cfi::TypeIdOptions::USE_CONCRETE_SELF, - ] - .into_iter() - .powerset() - .map(cfi::TypeIdOptions::from_iter) - { - let typeid = cfi::typeid_for_instance(self.tcx, instance, options); - let ignored = self.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { - ignorelist.contains_prefix(c"cfi", c"type", &type_name) - }); - if !ignored && typeids.insert(typeid.clone()) { - self.add_type_metadata(llfn, typeid.as_bytes()); + if !ignored { + if let Some(instance) = instance { + let mut typeids = FxIndexSet::default(); + for options in [ + cfi::TypeIdOptions::GENERALIZE_POINTERS, + cfi::TypeIdOptions::NORMALIZE_INTEGERS, + cfi::TypeIdOptions::USE_CONCRETE_SELF, + ] + .into_iter() + .powerset() + .map(cfi::TypeIdOptions::from_iter) + { + let typeid = cfi::typeid_for_instance(self.tcx, instance, options); + if typeids.insert(typeid.clone()) { + self.add_type_metadata(llfn, typeid.as_bytes()); + } } - } - } else { - for options in [ - cfi::TypeIdOptions::GENERALIZE_POINTERS, - cfi::TypeIdOptions::NORMALIZE_INTEGERS, - ] - .into_iter() - .powerset() - .map(cfi::TypeIdOptions::from_iter) - { - let typeid = cfi::typeid_for_fnabi(self.tcx, fn_abi, options); - let ignored = self - .sanitizer_ignorelist - .as_ref() - .is_some_and(|l| l.contains_prefix(c"cfi", c"type", &type_name)); - if !ignored { + } else { + for options in [ + cfi::TypeIdOptions::GENERALIZE_POINTERS, + cfi::TypeIdOptions::NORMALIZE_INTEGERS, + ] + .into_iter() + .powerset() + .map(cfi::TypeIdOptions::from_iter) + { + let typeid = cfi::typeid_for_fnabi(self.tcx, fn_abi, options); self.add_type_metadata(llfn, typeid.as_bytes()); } } From a24ff27d1e30d7ef84fdd1491146abe522326c84 Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Mon, 15 Jun 2026 08:51:49 +0000 Subject: [PATCH 4/4] Move is_sanitizer_type_ignored to the context --- compiler/rustc_codegen_llvm/src/builder.rs | 74 +++++++++------------- compiler/rustc_codegen_llvm/src/context.rs | 11 ++++ compiler/rustc_codegen_llvm/src/declare.rs | 14 +--- 3 files changed, 45 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 3b161e215618d..9ae051547e43c 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -31,7 +31,7 @@ use tracing::{debug, instrument}; use crate::abi::FnAbiLlvmExt; use crate::attributes; -use crate::common::{type_name_for_ignore_list, Funclet}; +use crate::common::Funclet; use crate::context::{CodegenCx, FullCx, GenericCx, SCx}; use crate::llvm::{ self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, FromGeneric, GEPNoWrapFlags, Metadata, TRUE, @@ -1887,14 +1887,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { options.insert(cfi::TypeIdOptions::NORMALIZE_INTEGERS); } - let type_name = type_name_for_ignore_list(self.tcx, fn_abi); - - if self - .cx - .sanitizer_ignorelist - .as_ref() - .is_some_and(|ignorelist| ignorelist.contains_prefix(c"cfi", c"type", &type_name)) - { + if self.cx.is_sanitizer_type_ignored(c"cfi", fn_abi) { return; } @@ -1938,46 +1931,41 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { llfn: &'ll Value, ) -> Option> { let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) }; - let kcfi_bundle = - if self.tcx.sess.is_sanitizer_kcfi_enabled() - && let Some(fn_abi) = fn_abi - && is_indirect_call + let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled() + && let Some(fn_abi) = fn_abi + && is_indirect_call + { + if let Some(fn_attrs) = fn_attrs + && fn_attrs.sanitizers.disabled.contains(SanitizerSet::KCFI) { - if let Some(fn_attrs) = fn_attrs - && fn_attrs.sanitizers.disabled.contains(SanitizerSet::KCFI) - { - return None; - } - if crate::llvm::HasStringAttribute(self.llfn(), "no-sanitize-kcfi") { - return None; - } - - let mut options = kcfi::TypeIdOptions::empty(); - if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() { - options.insert(kcfi::TypeIdOptions::GENERALIZE_POINTERS); - } - if self.tcx.sess.is_sanitizer_cfi_normalize_integers_enabled() { - options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); - } - - let type_name = type_name_for_ignore_list(self.tcx, fn_abi); + return None; + } + if crate::llvm::HasStringAttribute(self.llfn(), "no-sanitize-kcfi") { + return None; + } - if self.cx.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { - ignorelist.contains_prefix(c"kcfi", c"type", &type_name) - }) { - return None; - } + let mut options = kcfi::TypeIdOptions::empty(); + if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() { + options.insert(kcfi::TypeIdOptions::GENERALIZE_POINTERS); + } + if self.tcx.sess.is_sanitizer_cfi_normalize_integers_enabled() { + options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); + } - let kcfi_typeid = if let Some(instance) = instance { - kcfi::typeid_for_instance(self.tcx, instance, options) - } else { - kcfi::typeid_for_fnabi(self.tcx, fn_abi, options) - }; + if self.cx.is_sanitizer_type_ignored(c"kcfi", fn_abi) { + return None; + } - Some(llvm::OperandBundleBox::new("kcfi", &[self.const_u32(kcfi_typeid)])) + let kcfi_typeid = if let Some(instance) = instance { + kcfi::typeid_for_instance(self.tcx, instance, options) } else { - None + kcfi::typeid_for_fnabi(self.tcx, fn_abi, options) }; + + Some(llvm::OperandBundleBox::new("kcfi", &[self.const_u32(kcfi_typeid)])) + } else { + None + }; kcfi_bundle } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 2d632648b5b0f..c824c43e28ef3 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -788,6 +788,17 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { 1 << 6, ); } + + pub(crate) fn is_sanitizer_type_ignored( + &self, + sanitizer: &std::ffi::CStr, + fn_abi: &rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, + ) -> bool { + self.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { + let type_name = crate::common::type_name_for_ignore_list(self.tcx, fn_abi); + ignorelist.contains_prefix(sanitizer, c"type", &type_name) + }) + } } impl<'ll> SimpleCx<'ll> { pub(crate) fn get_type_of_global(&self, val: &'ll Value) -> &'ll Type { diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index a0dfbb2e79eb8..63276d1d3bec3 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -25,7 +25,7 @@ use tracing::debug; use crate::abi::FnAbiLlvmExt; use crate::attributes; -use crate::common::{type_name_for_ignore_list, AsCCharPtr}; +use crate::common::AsCCharPtr; use crate::context::{CodegenCx, GenericCx, SCx, SimpleCx}; use crate::llvm::AttributePlace::Function; use crate::llvm::{self, FromGeneric, Type, Value, Visibility}; @@ -193,10 +193,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { if self.tcx.sess.is_sanitizer_cfi_enabled() && !crate::llvm::HasStringAttribute(llfn, "no-sanitize-cfi") { - let type_name = type_name_for_ignore_list(self.tcx, fn_abi); - let ignored = self.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| { - ignorelist.contains_prefix(c"cfi", c"type", &type_name) - }); + let ignored = self.is_sanitizer_type_ignored(c"cfi", fn_abi); if !ignored { if let Some(instance) = instance { @@ -243,12 +240,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { options.insert(kcfi::TypeIdOptions::NORMALIZE_INTEGERS); } - let type_name = type_name_for_ignore_list(self.tcx, fn_abi); - - let ignored = self - .sanitizer_ignorelist - .as_ref() - .is_some_and(|l| l.contains_prefix(c"kcfi", c"type", &type_name)); + let ignored = self.is_sanitizer_type_ignored(c"kcfi", fn_abi); if !ignored { let kcfi_typeid = if let Some(instance) = instance {