Skip to content

Commit 626986f

Browse files
committed
Make Arguments constructors unsafe
1 parent 905edfc commit 626986f

File tree

4 files changed

+42
-1
lines changed

4 files changed

+42
-1
lines changed

core/src/fmt/mod.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,29 @@ enum FlagV1 {
334334
impl<'a> Arguments<'a> {
335335
/// When using the format_args!() macro, this function is used to generate the
336336
/// Arguments structure.
337+
#[cfg(not(bootstrap))]
338+
#[doc(hidden)]
339+
#[inline]
340+
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
341+
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
342+
pub const unsafe fn new_v1(
343+
pieces: &'a [&'static str],
344+
args: &'a [ArgumentV1<'a>],
345+
) -> Arguments<'a> {
346+
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
347+
panic!("invalid args");
348+
}
349+
Arguments { pieces, fmt: None, args }
350+
}
351+
#[cfg(bootstrap)]
337352
#[doc(hidden)]
338353
#[inline]
339354
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
340355
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
341356
pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
357+
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
358+
panic!("invalid args");
359+
}
342360
Arguments { pieces, fmt: None, args }
343361
}
344362

@@ -348,6 +366,19 @@ impl<'a> Arguments<'a> {
348366
/// `CountIsParam` or `CountIsNextParam` has to point to an argument
349367
/// created with `argumentusize`. However, failing to do so doesn't cause
350368
/// unsafety, but will ignore invalid .
369+
#[cfg(not(bootstrap))]
370+
#[doc(hidden)]
371+
#[inline]
372+
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
373+
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
374+
pub const unsafe fn new_v1_formatted(
375+
pieces: &'a [&'static str],
376+
args: &'a [ArgumentV1<'a>],
377+
fmt: &'a [rt::v1::Argument],
378+
) -> Arguments<'a> {
379+
Arguments { pieces, fmt: Some(fmt), args }
380+
}
381+
#[cfg(bootstrap)]
351382
#[doc(hidden)]
352383
#[inline]
353384
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
//
111111
// Language features:
112112
#![feature(abi_unadjusted)]
113+
#![feature(allow_internal_unsafe)]
113114
#![feature(allow_internal_unstable)]
114115
#![feature(asm)]
115116
#![feature(associated_type_bounds)]

core/src/macros/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ pub(crate) mod builtin {
828828
/// assert_eq!(s, format!("hello {}", "world"));
829829
/// ```
830830
#[stable(feature = "rust1", since = "1.0.0")]
831+
#[allow_internal_unsafe]
831832
#[allow_internal_unstable(fmt_internals)]
832833
#[rustc_builtin_macro]
833834
#[macro_export]

core/src/panicking.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,15 @@ pub fn panic(expr: &'static str) -> ! {
4747
// truncation and padding (even though none is used here). Using
4848
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
4949
// output binary, saving up to a few kilobytes.
50-
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
50+
panic_fmt(
51+
#[cfg(bootstrap)]
52+
fmt::Arguments::new_v1(&[expr], &[]),
53+
#[cfg(not(bootstrap))]
54+
// SAFETY: Arguments::new_v1 is safe with exactly one str and zero args
55+
unsafe {
56+
fmt::Arguments::new_v1(&[expr], &[])
57+
},
58+
);
5159
}
5260

5361
#[inline]

0 commit comments

Comments
 (0)