Skip to content

Commit 7762adc

Browse files
committed
Auto merge of #122456 - maurer:cfi-nonpassed, r=workingjubilee
CFI: Skip non-passed arguments Rust will occasionally rely on fn((), X) -> Y being compatible with fn(X) -> Y, since () is a non-passed argument. Relax CFI by choosing not to encode non-passed arguments. This PR was split off from #121962 as part of fixing the larger vtable compatibility issues. r? `@workingjubilee`
2 parents cdb683f + f2f0d25 commit 7762adc

6 files changed

+65
-39
lines changed

compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_middle::ty::{
1818
use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
1919
use rustc_span::def_id::DefId;
2020
use rustc_span::sym;
21-
use rustc_target::abi::call::{Conv, FnAbi};
21+
use rustc_target::abi::call::{Conv, FnAbi, PassMode};
2222
use rustc_target::abi::Integer;
2323
use rustc_target::spec::abi::Abi;
2424
use std::fmt::Write as _;
@@ -1040,19 +1040,27 @@ pub fn typeid_for_fnabi<'tcx>(
10401040
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
10411041

10421042
// Encode the parameter types
1043+
1044+
// We erase ZSTs as we go if the argument is skipped. This is an implementation detail of how
1045+
// MIR is currently treated by rustc, and subject to change in the future. Specifically, MIR
1046+
// interpretation today will allow skipped arguments to simply not be passed at a call-site.
10431047
if !fn_abi.c_variadic {
1044-
if !fn_abi.args.is_empty() {
1045-
for arg in fn_abi.args.iter() {
1046-
let ty = transform_ty(tcx, arg.layout.ty, transform_ty_options);
1047-
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
1048-
}
1049-
} else {
1048+
let mut pushed_arg = false;
1049+
for arg in fn_abi.args.iter().filter(|arg| arg.mode != PassMode::Ignore) {
1050+
pushed_arg = true;
1051+
let ty = transform_ty(tcx, arg.layout.ty, transform_ty_options);
1052+
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
1053+
}
1054+
if !pushed_arg {
10501055
// Empty parameter lists, whether declared as () or conventionally as (void), are
10511056
// encoded with a void parameter specifier "v".
10521057
typeid.push('v');
10531058
}
10541059
} else {
10551060
for n in 0..fn_abi.fixed_count as usize {
1061+
if fn_abi.args[n].mode == PassMode::Ignore {
1062+
continue;
1063+
}
10561064
let ty = transform_ty(tcx, fn_abi.args[n].layout.ty, transform_ty_options);
10571065
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
10581066
}

tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs

+26-24
Original file line numberDiff line numberDiff line change
@@ -47,40 +47,42 @@ pub fn foo() where
4747
let _: Type4 = <Foo>::bar;
4848
}
4949

50-
pub fn foo1(_: Type1) { }
50+
// Force arguments to be passed by using a reference. Otherwise, they may end up PassMode::Ignore
51+
52+
pub fn foo1(_: &Type1) { }
5153
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
52-
pub fn foo2(_: Type1, _: Type1) { }
54+
pub fn foo2(_: &Type1, _: &Type1) { }
5355
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
54-
pub fn foo3(_: Type1, _: Type1, _: Type1) { }
56+
pub fn foo3(_: &Type1, _: &Type1, _: &Type1) { }
5557
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
56-
pub fn foo4(_: Type2) { }
58+
pub fn foo4(_: &Type2) { }
5759
// CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
58-
pub fn foo5(_: Type2, _: Type2) { }
60+
pub fn foo5(_: &Type2, _: &Type2) { }
5961
// CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
60-
pub fn foo6(_: Type2, _: Type2, _: Type2) { }
62+
pub fn foo6(_: &Type2, _: &Type2, _: &Type2) { }
6163
// CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
62-
pub fn foo7(_: Type3) { }
64+
pub fn foo7(_: &Type3) { }
6365
// CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
64-
pub fn foo8(_: Type3, _: Type3) { }
66+
pub fn foo8(_: &Type3, _: &Type3) { }
6567
// CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
66-
pub fn foo9(_: Type3, _: Type3, _: Type3) { }
68+
pub fn foo9(_: &Type3, _: &Type3, _: &Type3) { }
6769
// CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
68-
pub fn foo10(_: Type4) { }
70+
pub fn foo10(_: &Type4) { }
6971
// CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
70-
pub fn foo11(_: Type4, _: Type4) { }
72+
pub fn foo11(_: &Type4, _: &Type4) { }
7173
// CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
72-
pub fn foo12(_: Type4, _: Type4, _: Type4) { }
74+
pub fn foo12(_: &Type4, _: &Type4, _: &Type4) { }
7375
// CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
7476

75-
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barE"}
76-
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barS_E"}
77-
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barS_S_E"}
78-
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooE"}
79-
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooS_E"}
80-
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooS_S_E"}
81-
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooE"}
82-
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooS_E"}
83-
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooS_S_E"}
84-
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barE"}
85-
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barS_E"}
86-
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barS_S_E"}
77+
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
78+
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"}
79+
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_S0_E"}
80+
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
81+
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
82+
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
83+
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
84+
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
85+
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
86+
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
87+
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
88+
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}

tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use core::ffi::*;
1212
pub fn foo1(_: ()) { }
1313
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
1414
pub fn foo2(_: (), _: c_void) { }
15-
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
15+
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
1616
pub fn foo3(_: (), _: c_void, _: c_void) { }
17-
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
17+
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
1818
pub fn foo4(_: *mut ()) { }
1919
// CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
2020
pub fn foo5(_: *mut (), _: *mut c_void) { }
@@ -131,8 +131,6 @@ pub fn foo60(_: &str, _: &str, _: &str) { }
131131
// CHECK: define{{.*}}5foo60{{.*}}!type ![[TYPE60:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
132132

133133
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvE"}
134-
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvvvE"}
135-
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvvvvE"}
136134
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvPvE"}
137135
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvPvS_E"}
138136
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvPvS_S_E"}

tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub struct Type2<'a> {
2828
member3: &'a Type2<'a>,
2929
}
3030

31-
pub struct Bar;
31+
pub struct Bar(i32);
3232

3333
// repr(transparent) user-defined generic type
3434
#[repr(transparent)]

tests/codegen/sanitizer/cfi/normalize-integers.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ pub fn foo11(_: (), _: usize, _: usize, _: usize) { }
4141
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64|u4i128}}E.normalized"}
4242
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64|u4i128}}S_E.normalized"}
4343
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64|u4i128}}S_S_E.normalized"}
44-
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvv{{u3u16|u3u32|u3u64|u4u128}}E.normalized"}
45-
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvv{{u3u16|u3u32|u3u64|u4u128}}S_E.normalized"}
46-
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvv{{u3u16|u3u32|u3u64|u4u128}}S_S_E.normalized"}
44+
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64|u4u128}}E.normalized"}
45+
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64|u4u128}}S_E.normalized"}
46+
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64|u4u128}}S_S_E.normalized"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Tests that converting a closure to a function pointer works
2+
// The notable thing being tested here is that when the closure does not capture anything,
3+
// the call method from its Fn trait takes a ZST representing its environment. The compiler then
4+
// uses the assumption that the ZST is non-passed to reify this into a function pointer.
5+
//
6+
// This checks that the reified function pointer will have the expected alias set at its call-site.
7+
8+
//@ needs-sanitizer-cfi
9+
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
10+
//@ only-linux
11+
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
12+
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
13+
//@ run-pass
14+
15+
pub fn main() {
16+
let f: &fn() = &((|| ()) as _);
17+
f();
18+
}

0 commit comments

Comments
 (0)