Skip to content

Commit 7630226

Browse files
committed
Auto merge of rust-lang#139632 - Darksonn:cfi-fmt, r=<try>
cfi: do not transmute function pointers in formatting code Follow-up to rust-lang#115954. Addresses rust-lang#115199 point 2. Related to rust-lang#128728. Discussion [on the LKML](https://lore.kernel.org/all/[email protected]/). cc `@maurer` `@rcvalle` `@RalfJung`
2 parents e1b06f7 + 17d4124 commit 7630226

File tree

3 files changed

+32
-34
lines changed

3 files changed

+32
-34
lines changed

Diff for: library/core/src/fmt/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8};
77
use crate::marker::PhantomData;
88
use crate::num::fmt as numfmt;
99
use crate::ops::Deref;
10-
use crate::{iter, mem, result, str};
10+
use crate::{iter, result, str};
1111

1212
mod builders;
1313
#[cfg(not(no_fp_fmt_parse))]

Diff for: library/core/src/fmt/rt.rs

+23-23
Original file line numberDiff line numberDiff line change
@@ -65,61 +65,66 @@ pub struct Argument<'a> {
6565
ty: ArgumentType<'a>,
6666
}
6767

68-
#[rustc_diagnostic_item = "ArgumentMethods"]
69-
impl Argument<'_> {
70-
#[inline]
71-
const fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
68+
macro_rules! argument_new {
69+
($t:ty, $x:expr, $f:expr) => {
7270
Argument {
7371
// INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
7472
// a `fn(&T, ...)`, so the invariant is maintained.
7573
ty: ArgumentType::Placeholder {
76-
value: NonNull::from_ref(x).cast(),
77-
// SAFETY: function pointers always have the same layout.
78-
formatter: unsafe { mem::transmute(f) },
74+
value: NonNull::<$t>::from_ref($x).cast(),
75+
formatter: |ptr: NonNull<()>, fmt: &mut Formatter<'_>| {
76+
let func = $f;
77+
// SAFETY: This is the same type as the `value` field.
78+
let r = unsafe { ptr.cast::<$t>().as_ref() };
79+
(func)(r, fmt)
80+
},
7981
_lifetime: PhantomData,
8082
},
8183
}
82-
}
84+
};
85+
}
8386

87+
#[rustc_diagnostic_item = "ArgumentMethods"]
88+
impl Argument<'_> {
8489
#[inline]
8590
pub fn new_display<T: Display>(x: &T) -> Argument<'_> {
86-
Self::new(x, Display::fmt)
91+
argument_new!(T, x, <T as Display>::fmt)
8792
}
8893
#[inline]
8994
pub fn new_debug<T: Debug>(x: &T) -> Argument<'_> {
90-
Self::new(x, Debug::fmt)
95+
argument_new!(T, x, <T as Debug>::fmt)
9196
}
9297
#[inline]
9398
pub fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> {
94-
Self::new(x, |_, _| Ok(()))
99+
argument_new!(T, x, |_: &T, _| Ok(()))
95100
}
96101
#[inline]
97102
pub fn new_octal<T: Octal>(x: &T) -> Argument<'_> {
98-
Self::new(x, Octal::fmt)
103+
argument_new!(T, x, <T as Octal>::fmt)
99104
}
100105
#[inline]
101106
pub fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> {
102-
Self::new(x, LowerHex::fmt)
107+
argument_new!(T, x, <T as LowerHex>::fmt)
103108
}
104109
#[inline]
105110
pub fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> {
106-
Self::new(x, UpperHex::fmt)
111+
argument_new!(T, x, <T as UpperHex>::fmt)
107112
}
108113
#[inline]
109114
pub fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> {
110-
Self::new(x, Pointer::fmt)
115+
argument_new!(T, x, <T as Pointer>::fmt)
111116
}
112117
#[inline]
113118
pub fn new_binary<T: Binary>(x: &T) -> Argument<'_> {
114-
Self::new(x, Binary::fmt)
119+
argument_new!(T, x, <T as Binary>::fmt)
115120
}
116121
#[inline]
117122
pub fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> {
118-
Self::new(x, LowerExp::fmt)
123+
argument_new!(T, x, <T as LowerExp>::fmt)
119124
}
120125
#[inline]
121126
pub fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> {
122-
Self::new(x, UpperExp::fmt)
127+
argument_new!(T, x, <T as UpperExp>::fmt)
123128
}
124129
#[inline]
125130
#[track_caller]
@@ -135,11 +140,6 @@ impl Argument<'_> {
135140
/// # Safety
136141
///
137142
/// This argument must actually be a placeholder argument.
138-
///
139-
// FIXME: Transmuting formatter in new and indirectly branching to/calling
140-
// it here is an explicit CFI violation.
141-
#[allow(inline_no_sanitize)]
142-
#[no_sanitize(cfi, kcfi)]
143143
#[inline]
144144
pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
145145
match self.ty {

Diff for: tests/coverage/closure.cov-map

+8-10
Original file line numberDiff line numberDiff line change
@@ -140,19 +140,17 @@ Number of file 0 mappings: 6
140140
- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10)
141141
Highest counter ID seen: c1
142142

143-
Function name: closure::main::{closure#18}
144-
Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e]
143+
Function name: closure::main::{closure#18} (unused)
144+
Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 11, 00, 12, 00, 01, 11, 01, 0e]
145145
Number of files: 1
146146
- file 0 => global file 1
147-
Number of expressions: 1
148-
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
147+
Number of expressions: 0
149148
Number of file 0 mappings: 4
150-
- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28)
151-
- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18)
152-
- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18)
153-
= (c0 - c1)
154-
- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14)
155-
Highest counter ID seen: c1
149+
- Code(Zero) at (prev + 25, 13) to (start + 2, 28)
150+
- Code(Zero) at (prev + 2, 29) to (start + 2, 18)
151+
- Code(Zero) at (prev + 2, 17) to (start + 0, 18)
152+
- Code(Zero) at (prev + 1, 17) to (start + 1, 14)
153+
Highest counter ID seen: (none)
156154

157155
Function name: closure::main::{closure#19}
158156
Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e]

0 commit comments

Comments
 (0)