Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 58dcd1f

Browse files
committed
Auto merge of rust-lang#123071 - rcvalle:rust-cfi-fix-method-fn-ptr-cast, r=compiler-errors
CFI: Fix methods as function pointer cast Fix casting between methods and function pointers by assigning a secondary type id to methods with their concrete self so they can be used as function pointers. This was split off from rust-lang#116404. cc `@compiler-errors` `@workingjubilee`
2 parents 1c19595 + 8e6b4e9 commit 58dcd1f

File tree

5 files changed

+84
-27
lines changed

5 files changed

+84
-27
lines changed

‎compiler/rustc_codegen_llvm/src/declare.rs‎

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ use crate::llvm;
1818
use crate::llvm::AttributePlace::Function;
1919
use crate::type_::Type;
2020
use crate::value::Value;
21+
use itertools::Itertools;
2122
use rustc_codegen_ssa::traits::TypeMembershipMethods;
23+
use rustc_data_structures::fx::FxIndexSet;
2224
use rustc_middle::ty::{Instance, Ty};
2325
use rustc_symbol_mangling::typeid::{
2426
kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
@@ -141,33 +143,31 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
141143

142144
if self.tcx.sess.is_sanitizer_cfi_enabled() {
143145
if let Some(instance) = instance {
144-
let typeid = typeid_for_instance(self.tcx, instance, TypeIdOptions::empty());
145-
self.set_type_metadata(llfn, typeid);
146-
let typeid =
147-
typeid_for_instance(self.tcx, instance, TypeIdOptions::GENERALIZE_POINTERS);
148-
self.add_type_metadata(llfn, typeid);
149-
let typeid =
150-
typeid_for_instance(self.tcx, instance, TypeIdOptions::NORMALIZE_INTEGERS);
151-
self.add_type_metadata(llfn, typeid);
152-
let typeid = typeid_for_instance(
153-
self.tcx,
154-
instance,
155-
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
156-
);
157-
self.add_type_metadata(llfn, typeid);
146+
let mut typeids = FxIndexSet::default();
147+
for options in [
148+
TypeIdOptions::GENERALIZE_POINTERS,
149+
TypeIdOptions::NORMALIZE_INTEGERS,
150+
TypeIdOptions::NO_SELF_TYPE_ERASURE,
151+
]
152+
.into_iter()
153+
.powerset()
154+
.map(TypeIdOptions::from_iter)
155+
{
156+
let typeid = typeid_for_instance(self.tcx, instance, options);
157+
if typeids.insert(typeid.clone()) {
158+
self.add_type_metadata(llfn, typeid);
159+
}
160+
}
158161
} else {
159-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::empty());
160-
self.set_type_metadata(llfn, typeid);
161-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::GENERALIZE_POINTERS);
162-
self.add_type_metadata(llfn, typeid);
163-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::NORMALIZE_INTEGERS);
164-
self.add_type_metadata(llfn, typeid);
165-
let typeid = typeid_for_fnabi(
166-
self.tcx,
167-
fn_abi,
168-
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
169-
);
170-
self.add_type_metadata(llfn, typeid);
162+
for options in
163+
[TypeIdOptions::GENERALIZE_POINTERS, TypeIdOptions::NORMALIZE_INTEGERS]
164+
.into_iter()
165+
.powerset()
166+
.map(TypeIdOptions::from_iter)
167+
{
168+
let typeid = typeid_for_fnabi(self.tcx, fn_abi, options);
169+
self.add_type_metadata(llfn, typeid);
170+
}
171171
}
172172
}
173173

‎compiler/rustc_symbol_mangling/src/typeid.rs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,20 @@ bitflags! {
1313
/// Options for typeid_for_fnabi.
1414
#[derive(Clone, Copy, Debug)]
1515
pub struct TypeIdOptions: u32 {
16+
/// Generalizes pointers for compatibility with Clang
17+
/// `-fsanitize-cfi-icall-generalize-pointers` option for cross-language LLVM CFI and KCFI
18+
/// support.
1619
const GENERALIZE_POINTERS = 1;
20+
/// Generalizes repr(C) user-defined type for extern function types with the "C" calling
21+
/// convention (or extern types) for cross-language LLVM CFI and KCFI support.
1722
const GENERALIZE_REPR_C = 2;
23+
/// Normalizes integers for compatibility with Clang
24+
/// `-fsanitize-cfi-icall-experimental-normalize-integers` option for cross-language LLVM
25+
/// CFI and KCFI support.
1826
const NORMALIZE_INTEGERS = 4;
27+
/// Do not perform self type erasure for attaching a secondary type id to methods with their
28+
/// concrete self so they can be used as function pointers.
29+
const NO_SELF_TYPE_ERASURE = 8;
1930
}
2031
}
2132

‎compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,8 @@ pub fn typeid_for_instance<'tcx>(
11441144
instance.args = strip_receiver_auto(tcx, instance.args);
11451145
}
11461146

1147-
if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
1147+
if !options.contains(EncodeTyOptions::NO_SELF_TYPE_ERASURE)
1148+
&& let Some(impl_id) = tcx.impl_of_method(instance.def_id())
11481149
&& let Some(trait_ref) = tcx.impl_trait_ref(impl_id)
11491150
{
11501151
let impl_method = tcx.associated_item(instance.def_id());
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Verifies that a secondary type metadata identifier is assigned to methods with their concrete
2+
// self so they can be used as function pointers.
3+
//
4+
//@ needs-sanitizer-cfi
5+
//@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
6+
7+
#![crate_type="lib"]
8+
9+
trait Trait1 {
10+
fn foo(&self);
11+
}
12+
13+
struct Type1;
14+
15+
impl Trait1 for Type1 {
16+
fn foo(&self) {}
17+
// CHECK: define{{.*}}3foo{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
18+
}
19+
20+
21+
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}6Trait1u6regionEEE"}
22+
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Type1EE"}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Verifies that casting a method to a function pointer works.
2+
//
3+
// FIXME(#122848): Remove only-linux when fixed.
4+
//@ only-linux
5+
//@ needs-sanitizer-cfi
6+
//@ compile-flags: -Clto -Copt-level=0 -Cprefer-dynamic=off -Ctarget-feature=-crt-static -Zsanitizer=cfi
7+
//@ run-pass
8+
9+
trait Trait1 {
10+
fn foo(&self);
11+
}
12+
13+
struct Type1;
14+
15+
impl Trait1 for Type1 {
16+
fn foo(&self) {}
17+
}
18+
19+
fn main() {
20+
let type1 = Type1 {};
21+
let f = <Type1 as Trait1>::foo;
22+
f(&type1);
23+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /