Skip to content

Commit 7fd0f60

Browse files
committed
CFI: Apply CFI shims to drops
Fixes: 118761
1 parent c9ff274 commit 7fd0f60

File tree

6 files changed

+72
-15
lines changed

6 files changed

+72
-15
lines changed

compiler/rustc_middle/src/ty/vtable.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ pub(super) fn vtable_allocation_provider<'tcx>(
5353
) -> AllocId {
5454
let (ty, poly_trait_ref) = key;
5555

56-
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
57-
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
58-
let trait_ref = tcx.erase_regions(trait_ref);
56+
let invoke_trait = poly_trait_ref
57+
.map(|poly_trait_ref| tcx.erase_regions(poly_trait_ref.with_self_ty(tcx, ty)));
5958

60-
tcx.vtable_entries(trait_ref)
59+
let vtable_entries = if let Some(invoke_trait) = invoke_trait {
60+
tcx.vtable_entries(invoke_trait)
6161
} else {
6262
TyCtxt::COMMON_VTABLE_ENTRIES
6363
};
@@ -83,7 +83,8 @@ pub(super) fn vtable_allocation_provider<'tcx>(
8383
let idx: u64 = u64::try_from(idx).unwrap();
8484
let scalar = match entry {
8585
VtblEntry::MetadataDropInPlace => {
86-
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
86+
let instance =
87+
ty::Instance::resolve_drop_in_place(tcx, ty).cfi_shim(tcx, invoke_trait);
8788
let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance);
8889
let fn_ptr = Pointer::from(fn_alloc_id);
8990
Scalar::from_pointer(fn_ptr, &tcx)

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ fn collect_items_rec<'tcx>(
384384
// Nested statics have no type.
385385
if !nested {
386386
let ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
387-
visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items);
387+
visit_drop_use(tcx, ty, None, true, starting_item.span, &mut used_items);
388388
}
389389

390390
recursion_depth_reset = None;
@@ -863,7 +863,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
863863
mir::TerminatorKind::Drop { ref place, .. } => {
864864
let ty = place.ty(self.body, self.tcx).ty;
865865
let ty = self.monomorphize(ty);
866-
visit_drop_use(self.tcx, ty, true, source, self.output);
866+
visit_drop_use(self.tcx, ty, None, true, source, self.output);
867867
}
868868
mir::TerminatorKind::InlineAsm { ref operands, .. } => {
869869
for op in operands {
@@ -925,11 +925,17 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
925925
fn visit_drop_use<'tcx>(
926926
tcx: TyCtxt<'tcx>,
927927
ty: Ty<'tcx>,
928+
invoke_trait: Option<ty::PolyTraitRef<'tcx>>,
928929
is_direct_call: bool,
929930
source: Span,
930931
output: &mut MonoItems<'tcx>,
931932
) {
932-
let instance = Instance::resolve_drop_in_place(tcx, ty);
933+
let mut instance = Instance::resolve_drop_in_place(tcx, ty);
934+
if tcx.sess.cfi_shims() && !is_direct_call {
935+
// The CFI shim may generate a direct call to the unshimmed drop
936+
visit_drop_use(tcx, ty, None, true, source, output);
937+
instance = instance.cfi_shim(tcx, invoke_trait);
938+
}
933939
visit_instance_use(tcx, instance, is_direct_call, source, output);
934940
}
935941

@@ -1201,8 +1207,10 @@ fn create_mono_items_for_vtable_methods<'tcx>(
12011207
assert!(!trait_ty.has_escaping_bound_vars() && !impl_ty.has_escaping_bound_vars());
12021208

12031209
if let ty::Dynamic(trait_ty, ..) = trait_ty.kind() {
1204-
if let Some(principal) = trait_ty.principal() {
1205-
let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
1210+
let invoke_trait =
1211+
trait_ty.principal().map(|principal| principal.with_self_ty(tcx, impl_ty));
1212+
1213+
if let Some(poly_trait_ref) = invoke_trait {
12061214
assert!(!poly_trait_ref.has_escaping_bound_vars());
12071215

12081216
// Walk all methods of the trait, including those of its supertraits
@@ -1224,10 +1232,10 @@ fn create_mono_items_for_vtable_methods<'tcx>(
12241232
})
12251233
.map(|item| create_fn_mono_item(tcx, item, source));
12261234
output.extend(methods);
1227-
}
1235+
};
12281236

12291237
// Also add the destructor.
1230-
visit_drop_use(tcx, impl_ty, false, source, output);
1238+
visit_drop_use(tcx, impl_ty, invoke_trait, false, source, output);
12311239
}
12321240
}
12331241

@@ -1252,7 +1260,7 @@ impl<'v> RootCollector<'_, 'v> {
12521260
debug!("RootCollector: ADT drop-glue for `{id:?}`",);
12531261

12541262
let ty = self.tcx.type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap();
1255-
visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
1263+
visit_drop_use(self.tcx, ty, None, true, DUMMY_SP, self.output);
12561264
}
12571265
}
12581266
DefKind::GlobalAsm => {

tests/codegen/sanitizer/kcfi-emit-type-metadata-trait-objects.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#![no_core]
1313

1414
#[lang="sized"]
15-
trait Sized { }
15+
pub trait Sized { }
1616
#[lang="copy"]
1717
trait Copy { }
1818
#[lang="receiver"]
@@ -28,7 +28,9 @@ impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b
2828
#[lang="freeze"]
2929
trait Freeze { }
3030
#[lang="drop_in_place"]
31-
fn drop_in_place_fn<T>() { }
31+
fn drop_in_place_fn<T: ?Sized>(_to_drop: *mut T) { }
32+
#[lang="unpin"]
33+
pub trait Unpin { }
3234

3335
pub trait Trait1 {
3436
fn foo(&self);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Validate that objects that might have custom drop can be dropped with CFI on. See #118761
2+
3+
//@ needs-sanitizer-cfi
4+
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi -C codegen-units=1
5+
//@ compile-flags: -C opt-level=0
6+
//@ run-pass
7+
8+
struct Bar;
9+
trait Fooable {}
10+
impl Fooable for Bar {}
11+
12+
fn main() {
13+
let _: Box<dyn Fooable> = Box::new(Bar);
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ needs-sanitizer-cfi
2+
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
3+
//@ compile-flags: -C codegen-units=1 -C opt-level=0
4+
//@ run-pass
5+
6+
use std::env;
7+
8+
fn main() {
9+
env::current_exe().unwrap();
10+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Check trait objects run correctly
2+
3+
//@ needs-sanitizer-cfi
4+
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
5+
//@ compile-flags: -C codegen-units=1 -C opt-level=0
6+
//@ run-pass
7+
8+
struct Bar;
9+
trait Fooable {
10+
fn foo(&self) -> i32;
11+
}
12+
13+
impl Fooable for Bar {
14+
fn foo(&self) -> i32 {
15+
3
16+
}
17+
}
18+
19+
fn main() {
20+
let bar: Box<dyn Fooable> = Box::new(Bar);
21+
bar.foo();
22+
}

0 commit comments

Comments
 (0)