Skip to content

Commit f6bfdc9

Browse files
Move the show_usize marker function to a static
Currently, function items are always tagged unnamed_addr, which means that casting a function to a function pointer is not guaranteed to produce a deterministic address. However, once a function pointer is created, we do expect that to remain stable. So, this changes the show_usize function to a static containing a function pointer and uses that for comparisons. Notably, a *static* may have 'unstable' address, but the function pointer within it must be constant. Resolves issue 58320.
1 parent 34ef8f5 commit f6bfdc9

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

src/libcore/fmt/mod.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,19 @@ pub struct ArgumentV1<'a> {
255255
formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
256256
}
257257

258-
impl<'a> ArgumentV1<'a> {
259-
#[inline(never)]
260-
fn show_usize(x: &usize, f: &mut Formatter<'_>) -> Result {
261-
Display::fmt(x, f)
262-
}
258+
// This gurantees a single stable value for the function pointer associated with
259+
// indices/counts in the formatting infrastructure.
260+
//
261+
// Note that a function defined as such would not be correct as functions are
262+
// always tagged unnamed_addr with the current lowering to LLVM IR, so their
263+
// address is not considered important to LLVM and as such the as_usize cast
264+
// could have been miscompiled. In practice, we never call as_usize on non-usize
265+
// containing data (as a matter of static generation of the formatting
266+
// arguments), so this is merely an additional check.
267+
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
268+
static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {};
263269

270+
impl<'a> ArgumentV1<'a> {
264271
#[doc(hidden)]
265272
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
266273
pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
@@ -270,11 +277,13 @@ impl<'a> ArgumentV1<'a> {
270277
#[doc(hidden)]
271278
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
272279
pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
273-
ArgumentV1::new(x, ArgumentV1::show_usize)
280+
ArgumentV1::new(x, USIZE_MARKER)
274281
}
275282

276283
fn as_usize(&self) -> Option<usize> {
277-
if self.formatter as usize == ArgumentV1::show_usize as usize {
284+
if self.formatter as usize == USIZE_MARKER as usize {
285+
// SAFETY: The `formatter` field is only set to USIZE_MARKER if
286+
// the value is a usize, so this is safe
278287
Some(unsafe { *(self.value as *const _ as *const usize) })
279288
} else {
280289
None

0 commit comments

Comments
 (0)