diff options
| author | Mark Rousskov <mark.simulacrum@gmail.com> | 2020-02-16 10:17:01 -0500 |
|---|---|---|
| committer | Mark Rousskov <mark.simulacrum@gmail.com> | 2020-02-17 09:18:33 -0500 |
| commit | f6bfdc95445180aee579dcacc6e6bdc4e6ecf56f (patch) | |
| tree | 6fe6da3b410876a8212136d6795de6e247529f2c /src | |
| parent | 34ef8f5441d5335c4177abd622383ed34a6e9315 (diff) | |
| download | rust-f6bfdc95445180aee579dcacc6e6bdc4e6ecf56f.tar.gz rust-f6bfdc95445180aee579dcacc6e6bdc4e6ecf56f.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/fmt/mod.rs | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0c51a802fab..993b1073493 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -255,12 +255,19 @@ pub struct ArgumentV1<'a> { formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } -impl<'a> ArgumentV1<'a> { - #[inline(never)] - fn show_usize(x: &usize, f: &mut Formatter<'_>) -> Result { - Display::fmt(x, f) - } +// This gurantees a single stable value for the function pointer associated with +// indices/counts in the formatting infrastructure. +// +// Note that a function defined as such would not be correct as functions are +// always tagged unnamed_addr with the current lowering to LLVM IR, so their +// address is not considered important to LLVM and as such the as_usize cast +// could have been miscompiled. In practice, we never call as_usize on non-usize +// containing data (as a matter of static generation of the formatting +// arguments), so this is merely an additional check. +#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] +static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {}; +impl<'a> ArgumentV1<'a> { #[doc(hidden)] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> { @@ -270,11 +277,13 @@ impl<'a> ArgumentV1<'a> { #[doc(hidden)] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] pub fn from_usize(x: &usize) -> ArgumentV1<'_> { - ArgumentV1::new(x, ArgumentV1::show_usize) + ArgumentV1::new(x, USIZE_MARKER) } fn as_usize(&self) -> Option<usize> { - if self.formatter as usize == ArgumentV1::show_usize as usize { + if self.formatter as usize == USIZE_MARKER as usize { + // SAFETY: The `formatter` field is only set to USIZE_MARKER if + // the value is a usize, so this is safe Some(unsafe { *(self.value as *const _ as *const usize) }) } else { None |
