From 284da5d6b44ffaf22db50f4c30f5d941a471b26c Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Mon, 8 Apr 2024 16:37:06 +0000 Subject: [PATCH] CFI: Fix ICE in KCFI non-associated function pointers We oddly weren't testing the more usual case of casting non-methods to function pointers. The KCFI shim insertion logic would ICE on these due to asking for an irrefutable associated item if we cast a function to a function pointer without needing a traditional shim. --- compiler/rustc_middle/src/ty/instance.rs | 5 ++++- .../{cfi-method-fn-ptr-cast.rs => cfi-fn-ptr.rs} | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) rename tests/ui/sanitizer/{cfi-method-fn-ptr-cast.rs => cfi-fn-ptr.rs} (85%) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 4a7720b38f850..f8f59fbeab449 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -520,7 +520,10 @@ impl<'tcx> Instance<'tcx> { // Reify `Trait::method` implementations if KCFI is enabled // FIXME(maurer) only reify it if it is a vtable-safe function _ if tcx.sess.is_sanitizer_kcfi_enabled() - && tcx.associated_item(def_id).trait_item_def_id.is_some() => + && tcx + .opt_associated_item(def_id) + .and_then(|assoc| assoc.trait_item_def_id) + .is_some() => { // If this function could also go in a vtable, we need to `ReifyShim` it with // KCFI because it can only attach one type per function. diff --git a/tests/ui/sanitizer/cfi-method-fn-ptr-cast.rs b/tests/ui/sanitizer/cfi-fn-ptr.rs similarity index 85% rename from tests/ui/sanitizer/cfi-method-fn-ptr-cast.rs rename to tests/ui/sanitizer/cfi-fn-ptr.rs index 8f79de1174883..505b4b8e7f032 100644 --- a/tests/ui/sanitizer/cfi-method-fn-ptr-cast.rs +++ b/tests/ui/sanitizer/cfi-fn-ptr.rs @@ -1,4 +1,4 @@ -// Verifies that casting a method to a function pointer works. +// Verifies that casting to a function pointer works. //@ revisions: cfi kcfi // FIXME(#122848) Remove only-linux once OSX CFI binaries work @@ -46,6 +46,8 @@ impl Trait1 for Type1 { fn foo(&self) {} } +fn foo(_: &T) {} + fn main() { let type1 = Type1 {}; let f = ::foo; @@ -53,5 +55,7 @@ fn main() { // Check again with different optimization barriers S2 { f: ::foo }.foo(&S); // Check mismatched #[track_caller] - S2 { f: ::bar }.foo(&S) + S2 { f: ::bar }.foo(&S); + // Check non-method functions + S2 { f: foo }.foo(&S) }