Skip to content

Commit cff5996

Browse files
committed
PR Feedback: To Encoder - Treat data pointer the same as fn in Option handling
1 parent 54893fd commit cff5996

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

compiler/rustc_middle/src/ptrauth/discriminator.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,17 +316,31 @@ enum ClangDiscTy<'tcx> {
316316
Void,
317317
}
318318

319-
// Canonicalize `Option<fn ptr>` to `fn ptr`. This is so that we can express C's null ptr argument.
320-
// Please see: pauth-fn-ptr-type-discrimination-option-callback.rs,
319+
// Canonicalize Option-wrapped pointer types used to model C nullable pointers.
320+
//
321+
// Rust and Clang should compute identical discriminators for equivalent C APIs.
322+
// Clang does not distinguish nullable from non-nullable pointer types when
323+
// computing function pointer authentication discriminators, so
324+
// `Option<fn>` and `Option<*mut T>` are encoded identically to their
325+
// underlying pointer types.
326+
//
327+
// Although `Option<*mut T>` is not considered FFI-safe by Rust and triggers the
328+
// `improper_ctypes`/`improper_ctypes_definitions` lints, this is a warning
329+
// rather than a hard error. Canonicalizing it here preserves Clang-compatible
330+
// discriminator computation.
331+
//
332+
// Please see the following tests for sample use cases:
333+
// pauth-fn-ptr-type-discrimination-option-callback.rs,
321334
// pauth-fn-ptr-type-discrimination-option-return.rs and pauth-fn-ptr-type-discrimination-option.rs
322335
fn canonicalize_c_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
323336
if let ty::Adt(def, args) = ty.kind()
324337
&& tcx.is_diagnostic_item(sym::Option, def.did())
325338
{
326339
let inner = args.type_at(0);
327340

328-
if matches!(inner.kind(), ty::FnPtr(..)) {
329-
return inner;
341+
match inner.kind() {
342+
ty::FnPtr(..) | ty::RawPtr(..) => return inner,
343+
_ => {}
330344
}
331345
}
332346

tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-option-callback.rs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,28 @@
2525
// int f_opt(FnCallback cb);
2626
// int f_raw(FnCallback cb);
2727
//
28+
// int d_opt(void *ctx);
29+
// int d_raw(void *ctx);
30+
//
2831
// int callback_i32(int);
2932
//
3033
// int (*T_OPT)(FnCallback) = f_opt;
3134
// int (*T_RAW)(FnCallback) = f_raw;
3235
//
36+
// int (*D_OPT)(void *) = d_opt;
37+
// int (*D_RAW)(void *) = d_raw;
3338
// int main(void) {
39+
// /* function pointers */
3440
// T_OPT(callback_i32);
3541
// T_OPT(NULL);
3642
//
3743
// T_RAW(callback_i32);
3844
//
45+
// /* data pointers */
46+
// int x = 42;
47+
// D_OPT(&x);
48+
// D_OPT(NULL);
49+
//
3950
// return 0;
4051
// }
4152
// ```
@@ -46,16 +57,23 @@
4657
#![crate_type = "lib"]
4758

4859
extern crate minicore;
49-
use minicore::Option;
5060
use minicore::Option::{None, Some};
61+
use minicore::{Option, c_void};
5162

5263
extern "C" {
5364
fn f_opt(cb: Option<unsafe extern "C" fn(i32) -> i32>) -> i32;
5465
fn f_raw(cb: unsafe extern "C" fn(i32) -> i32) -> i32;
66+
67+
fn g_opt(ctx: Option<*mut c_void>) -> i32;
68+
fn g_raw(ctx: *mut c_void) -> i32;
69+
70+
fn callback_i32(x: i32) -> i32;
5571
}
5672

5773
type FnOpt = unsafe extern "C" fn(Option<unsafe extern "C" fn(i32) -> i32>) -> i32;
5874
type FnRaw = unsafe extern "C" fn(unsafe extern "C" fn(i32) -> i32) -> i32;
75+
type DataOpt = unsafe extern "C" fn(Option<*mut c_void>) -> i32;
76+
type DataRaw = unsafe extern "C" fn(*mut c_void) -> i32;
5977

6078
#[used]
6179
// DISC: @{{.*}}T_OPT = constant ptr ptrauth (ptr @{{.*}}f_opt, i32 0, i64 12410), align 8
@@ -66,13 +84,21 @@ static T_OPT: FnOpt = f_opt;
6684
// NO_DISC: @{{.*}}T_RAW = constant ptr ptrauth (ptr @{{.*}}f_raw, i32 0), align 8
6785
static T_RAW: FnRaw = f_raw;
6886

69-
unsafe extern "C" {
70-
fn callback_i32(x: i32) -> i32;
71-
}
87+
// DISC: @{{.*}}G_OPT = constant ptr ptrauth (ptr @{{.*}}g_opt, i32 0, i64 12410), align 8
88+
// NO_DISC: @{{.*}}G_OPT = constant ptr ptrauth (ptr @{{.*}}g_opt, i32 0), align 8
89+
#[used]
90+
static G_OPT: DataOpt = g_opt;
7291

92+
// DISC: @{{.*}}G_RAW = constant ptr ptrauth (ptr @{{.*}}g_raw, i32 0, i64 12410), align 8
93+
// NO_DISC: @{{.*}}G_RAW = constant ptr ptrauth (ptr @{{.*}}g_raw, i32 0), align 8
94+
#[used]
95+
static G_RAW: DataRaw = g_raw;
7396
// CHECK-LABEL: main
7497
pub fn main() {
98+
let mut x = 42i32;
99+
75100
unsafe {
101+
// Function pointers
76102
//DISC: call i32 ptrauth (ptr @f_opt, i32 0, i64 12410)(ptr ptrauth (ptr @callback_i32, i32 0, i64 2981)) {{.*}} [ "ptrauth"(i32 0, i64 12410) ]
77103
//NO_DISC: call i32 ptrauth (ptr @f_opt, i32 0)(ptr ptrauth (ptr @callback_i32, i32 0)) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
78104
let _ = T_OPT(Some(callback_i32));
@@ -82,5 +108,17 @@ pub fn main() {
82108
// DISC: call i32 ptrauth (ptr @f_raw, i32 0, i64 12410)(ptr ptrauth (ptr @callback_i32, i32 0, i64 2981)) {{.*}} [ "ptrauth"(i32 0, i64 12410) ]
83109
// NO_DISC: call i32 ptrauth (ptr @f_raw, i32 0)(ptr ptrauth (ptr @callback_i32, i32 0)) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
84110
let _ = T_RAW(callback_i32);
111+
112+
// Data pointers
113+
// DISC: call i32 ptrauth (ptr @g_opt, i32 0, i64 12410){{.*}} [ "ptrauth"(i32 0, i64 12410) ]
114+
// NO_DISC: call i32 ptrauth (ptr @g_opt, i32 0){{.*}} [ "ptrauth"(i32 0, i64 0) ]
115+
let _ = G_OPT(Some((&mut x as *mut i32) as *mut c_void));
116+
// DISC: call i32 ptrauth (ptr @g_opt, i32 0, i64 12410){{.*}} [ "ptrauth"(i32 0, i64 12410) ]
117+
// NO_DISC: call i32 ptrauth (ptr @g_opt, i32 0){{.*}} [ "ptrauth"(i32 0, i64 0) ]
118+
let _ = G_OPT(None);
119+
120+
// DISC: call i32 ptrauth (ptr @g_raw, i32 0, i64 12410){{.*}} [ "ptrauth"(i32 0, i64 12410) ]
121+
// NO_DISC: call i32 ptrauth (ptr @g_raw, i32 0){{.*}} [ "ptrauth"(i32 0, i64 0) ]
122+
let _ = G_RAW((&mut x as *mut i32) as *mut c_void);
85123
}
86124
}

0 commit comments

Comments
 (0)