rust-lang / rust-lang/rust

ICE: `format_args!` optimization can construct a `&str` longer than `isize::MAX`

Open
#138,811 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-fmt C-bug I-ICE requires-internal-features T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Optimizations for format_args! can construct a &str constant longer than isize::MAX or even usize::MAX. I have observed this when cross-compiling to a 32-bit target from a 64-bit host. If compiled on a 32-bit host, rustc would probably panic in String resizing.

Setup
#![allow(internal_features)]
#![feature(core_intrinsics)]

use core::{fmt, intrinsics};

macro_rules! concat_repeat(
    (16, $($x:literal)*) => { concat_repeat!(15, $($x)* $($x)*) };
    (15, $($x:literal)*) => { concat_repeat!(14, $($x)* $($x)*) };
    (14, $($x:literal)*) => { concat_repeat!(13, $($x)* $($x)*) };
    (13, $($x:literal)*) => { concat_repeat!(12, $($x)* $($x)*) };
    (12, $($x:literal)*) => { concat_repeat!(11, $($x)* $($x)*) };
    (11, $($x:literal)*) => { concat_repeat!(10, $($x)* $($x)*) };
    (10, $($x:literal)*) => { concat_repeat!(9, $($x)* $($x)*) };
    (9, $($x:literal)*) => { concat_repeat!(8, $($x)* $($x)*) };
    (8, $($x:literal)*) => { concat_repeat!(7, $($x)* $($x)*) };
    (7, $($x:literal)*) => { concat_repeat!(6, $($x)* $($x)*) };
    (6, $($x:literal)*) => { concat_repeat!(5, $($x)* $($x)*) };
    (5, $($x:literal)*) => { concat_repeat!(4, $($x)* $($x)*) };
    (4, $($x:literal)*) => { concat_repeat!(3, $($x)* $($x)*) };
    (3, $($x:literal)*) => { concat_repeat!(2, $($x)* $($x)*) };
    (2, $($x:literal)*) => { concat_repeat!(1, $($x)* $($x)*) };
    (1, $($x:literal)*) => { concat!($($x),*, $($x),*) };
);

// fmt::Arguments::as_statically_known_str
#[inline]
fn as_statically_known_str(args: &fmt::Arguments<'_>) -> Option<&'static str> {
    let s = args.as_str();
    if intrinsics::is_val_statically_known(s.is_some()) {
        s
    } else {
        None
    }
}

fn print_len(args: fmt::Arguments<'_>) {
    let s = as_statically_known_str(&args).expect("statically known");
    println!("len = {}", s.len());
}
isize::MAX overflow

This format_args! is optimized to a constant &str with length 2147483648 (i32::MAX + 1).

fn main() {
    print_len(format_args!(
        concat_repeat!(8, "{x}{x}{x}{x}{x}{x}{x}{x}"),
        x = concat_repeat!(15, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
    ));
}

Compilation produces this error:

$ cargo build --release --target=i686-unknown-linux-gnu
error[E0080]: it is undefined behavior to use this value
  --> src/main.rs:36:1
   |
36 | fn main() {
   | ^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered invalid reference metadata: slice is bigger than largest supported object
   |
   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
   = note: the raw bytes of the constant (size: 4, align: 4) {
               ╾─a6<imm>─╼                                     │ ╾──╼
           }

note: erroneous constant encountered
  --> src/main.rs:22:30
   |
22 |     (1, $($x:literal)*) => { concat!($($x),*, $($x),*) };
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^
...
38 |         concat_repeat!(8, "{x}{x}{x}{x}{x}{x}{x}{x}"),
   |         --------------------------------------------- in this macro invocation
   |
   = note: this note originates in the macro `concat` which comes from the expansion of the macro `concat_repeat` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0080`.
error: could not compile `fmt-large-string` (bin "fmt-large-string") due to 1 previous error
usize::MAX overflow

This format_args! is optimized to a constant &str with length 4294967296 (1 << 32).

fn main() {
    print_len(format_args!(
        concat_repeat!(8, "{x}{x}{x}{x}{x}{x}{x}{x}"),
        x = concat_repeat!(16, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
    ));
}

Compilation aborts with this ICE:

$ cargo build --release --target=i686-unknown-linux-gnu
thread 'rustc' panicked at /rustc/78948ac259253ce89effca1e8bb64d16f4684aa4/compiler/rustc_middle/src/mir/interpret/value.rs:139:32:
Box<dyn Any>
stack backtrace:
   0:        0x117933967 - std::backtrace::Backtrace::create::he72e5c6ec1676771
   1:        0x1179338b5 - std::backtrace::Backtrace::force_capture::h83527e80780e82cc
   2:        0x11552e127 - std[e6c9211e353aebe9]::panicking::update_hook::<alloc[ec63ab7aac1f102d]::boxed::Box<rustc_driver_impl[8c05a4638ee6701e]::install_ice_hook::{closure#1}>>::{closure#0}
   3:        0x11794fb23 - std::panicking::rust_panic_with_hook::h46cbd39e2fba8522
   4:        0x1155c4ef7 - std[e6c9211e353aebe9]::panicking::begin_panic::<rustc_errors[3696162f341b2643]::ExplicitBug>::{closure#0}
   5:        0x1155b0289 - std[e6c9211e353aebe9]::sys::backtrace::__rust_end_short_backtrace::<std[e6c9211e353aebe9]::panicking::begin_panic<rustc_errors[3696162f341b2643]::ExplicitBug>::{closure#0}, !>
   6:        0x11ace515e - std[e6c9211e353aebe9]::panicking::begin_panic::<rustc_errors[3696162f341b2643]::ExplicitBug>
   7:        0x11ace5716 - <rustc_errors[3696162f341b2643]::diagnostic::BugAbort as rustc_errors[3696162f341b2643]::diagnostic::EmissionGuarantee>::emit_producing_guarantee
   8:        0x11ad7322c - rustc_middle[a14ca4759a2c046f]::util::bug::opt_span_bug_fmt::<rustc_span[e538c9ec2b20cab]::span_encoding::Span>::{closure#0}
   9:        0x1163c9217 - rustc_middle[a14ca4759a2c046f]::ty::context::tls::with_opt::<rustc_middle[a14ca4759a2c046f]::util::bug::opt_span_bug_fmt<rustc_span[e538c9ec2b20cab]::span_encoding::Span>::{closure#0}, !>::{closure#0}
  10:        0x1163c8d25 - rustc_middle[a14ca4759a2c046f]::ty::context::tls::with_context_opt::<rustc_middle[a14ca4759a2c046f]::ty::context::tls::with_opt<rustc_middle[a14ca4759a2c046f]::util::bug::opt_span_bug_fmt<rustc_span[e538c9ec2b20cab]::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
  11:        0x11ad7310b - rustc_middle[a14ca4759a2c046f]::util::bug::bug_fmt
  12:        0x11ad8a899 - <rustc_middle[a14ca4759a2c046f]::mir::interpret::value::Scalar<rustc_middle[a14ca4759a2c046f]::mir::interpret::AllocId>>::from_uint::<u128>::{closure#0}
  13:        0x11662629c - <rustc_const_eval[7027bb1ad2ba1c5d]::interpret::operand::Immediate>::new_slice::<rustc_const_eval[7027bb1ad2ba1c5d]::interpret::eval_context::InterpCx<rustc_const_eval[7027bb1ad2ba1c5d]::const_eval::dummy_machine::DummyMachine>>
  14:        0x11668f04e - <rustc_const_eval[7027bb1ad2ba1c5d]::interpret::eval_context::InterpCx<rustc_const_eval[7027bb1ad2ba1c5d]::const_eval::dummy_machine::DummyMachine>>::eval_mir_constant::{closure#0}
  15:        0x1167c092e - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator>::eval_constant
  16:        0x1167c17c9 - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator as rustc_middle[a14ca4759a2c046f]::mir::visit::Visitor>::visit_assign
  17:        0x1167c7272 - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator as rustc_middle[a14ca4759a2c046f]::mir::visit::Visitor>::visit_basic_block_data
  18:        0x1167c12b5 - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator as rustc_middle[a14ca4759a2c046f]::mir::visit::Visitor>::visit_body
  19:        0x1167bdb0c - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::KnownPanicsLint as rustc_mir_transform[e6e01cd5aad92b91]::pass_manager::MirLint>::run_lint
  20:        0x116724e3e - rustc_mir_transform[e6e01cd5aad92b91]::pass_manager::run_passes_inner
  21:        0x11674c2f8 - rustc_mir_transform[e6e01cd5aad92b91]::run_analysis_to_runtime_passes
  22:        0x11674d32b - rustc_mir_transform[e6e01cd5aad92b91]::promoted_mir
  23:        0x116ec6b36 - rustc_query_impl[4198737f17c2ba68]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[4198737f17c2ba68]::query_impl::promoted_mir::dynamic_query::{closure#2}::{closure#0}, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 8usize]>>
  24:        0x116c65b59 - rustc_query_system[e1590dd222ee792c]::query::plumbing::try_execute_query::<rustc_query_impl[4198737f17c2ba68]::DynamicConfig<rustc_query_system[e1590dd222ee792c]::query::caches::DefIdCache<rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 8usize]>>, false, false, false>, rustc_query_impl[4198737f17c2ba68]::plumbing::QueryCtxt, false>
  25:        0x116ee4d74 - rustc_query_impl[4198737f17c2ba68]::query_impl::promoted_mir::get_query_non_incr::__rust_end_short_backtrace
  26:        0x1154a4550 - rustc_const_eval[7027bb1ad2ba1c5d]::const_eval::eval_queries::eval_to_allocation_raw_provider
  27:        0x116ec976c - rustc_query_impl[4198737f17c2ba68]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[4198737f17c2ba68]::query_impl::eval_to_allocation_raw::dynamic_query::{closure#2}::{closure#0}, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 24usize]>>
  28:        0x116e7aa5e - <rustc_query_impl[4198737f17c2ba68]::query_impl::eval_to_allocation_raw::dynamic_query::{closure#2} as core[c2a971250a84775]::ops::function::FnOnce<(rustc_middle[a14ca4759a2c046f]::ty::context::TyCtxt, rustc_middle[a14ca4759a2c046f]::ty::PseudoCanonicalInput<rustc_middle[a14ca4759a2c046f]::mir::interpret::GlobalId>)>>::call_once
  29:        0x116c9de27 - rustc_query_system[e1590dd222ee792c]::query::plumbing::try_execute_query::<rustc_query_impl[4198737f17c2ba68]::DynamicConfig<rustc_query_system[e1590dd222ee792c]::query::caches::DefaultCache<rustc_middle[a14ca4759a2c046f]::ty::PseudoCanonicalInput<rustc_middle[a14ca4759a2c046f]::mir::interpret::GlobalId>, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 24usize]>>, false, false, false>, rustc_query_impl[4198737f17c2ba68]::plumbing::QueryCtxt, false>
  30:        0x116f06130 - rustc_query_impl[4198737f17c2ba68]::query_impl::eval_to_allocation_raw::get_query_non_incr::__rust_end_short_backtrace
  31:        0x1154a02cc - rustc_const_eval[7027bb1ad2ba1c5d]::const_eval::eval_queries::eval_to_const_value_raw_provider
  32:        0x116ec9f3c - rustc_query_impl[4198737f17c2ba68]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[4198737f17c2ba68]::query_impl::eval_to_const_value_raw::dynamic_query::{closure#2}::{closure#0}, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 24usize]>>
  33:        0x116e8004e - <rustc_query_impl[4198737f17c2ba68]::query_impl::eval_to_const_value_raw::dynamic_query::{closure#2} as core[c2a971250a84775]::ops::function::FnOnce<(rustc_middle[a14ca4759a2c046f]::ty::context::TyCtxt, rustc_middle[a14ca4759a2c046f]::ty::PseudoCanonicalInput<rustc_middle[a14ca4759a2c046f]::mir::interpret::GlobalId>)>>::call_once
  34:        0x116ca0702 - rustc_query_system[e1590dd222ee792c]::query::plumbing::try_execute_query::<rustc_query_impl[4198737f17c2ba68]::DynamicConfig<rustc_query_system[e1590dd222ee792c]::query::caches::DefaultCache<rustc_middle[a14ca4759a2c046f]::ty::PseudoCanonicalInput<rustc_middle[a14ca4759a2c046f]::mir::interpret::GlobalId>, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 24usize]>>, false, true, false>, rustc_query_impl[4198737f17c2ba68]::plumbing::QueryCtxt, false>
  35:        0x116f06cf0 - rustc_query_impl[4198737f17c2ba68]::query_impl::eval_to_const_value_raw::get_query_non_incr::__rust_end_short_backtrace
  36:        0x116439c1d - <rustc_middle[a14ca4759a2c046f]::ty::context::TyCtxt>::const_eval_global_id
  37:        0x116439057 - <rustc_middle[a14ca4759a2c046f]::ty::context::TyCtxt>::const_eval_resolve
  38:        0x11668ed1c - <rustc_const_eval[7027bb1ad2ba1c5d]::interpret::eval_context::InterpCx<rustc_const_eval[7027bb1ad2ba1c5d]::const_eval::dummy_machine::DummyMachine>>::eval_mir_constant::{closure#0}
  39:        0x1167c092e - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator>::eval_constant
  40:        0x1167c1ab6 - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator as rustc_middle[a14ca4759a2c046f]::mir::visit::Visitor>::visit_assign
  41:        0x1167c7272 - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator as rustc_middle[a14ca4759a2c046f]::mir::visit::Visitor>::visit_basic_block_data
  42:        0x1167c12b5 - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::ConstPropagator as rustc_middle[a14ca4759a2c046f]::mir::visit::Visitor>::visit_body
  43:        0x1167bdb0c - <rustc_mir_transform[e6e01cd5aad92b91]::known_panics_lint::KnownPanicsLint as rustc_mir_transform[e6e01cd5aad92b91]::pass_manager::MirLint>::run_lint
  44:        0x116724e3e - rustc_mir_transform[e6e01cd5aad92b91]::pass_manager::run_passes_inner
  45:        0x11674c2f8 - rustc_mir_transform[e6e01cd5aad92b91]::run_analysis_to_runtime_passes
  46:        0x11674bf0c - rustc_mir_transform[e6e01cd5aad92b91]::mir_drops_elaborated_and_const_checked
  47:        0x116ecb23a - rustc_query_impl[4198737f17c2ba68]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[4198737f17c2ba68]::query_impl::mir_drops_elaborated_and_const_checked::dynamic_query::{closure#2}::{closure#0}, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 8usize]>>
  48:        0x116cf5610 - rustc_query_system[e1590dd222ee792c]::query::plumbing::try_execute_query::<rustc_query_impl[4198737f17c2ba68]::DynamicConfig<rustc_data_structures[be3606a25063c5fa]::vec_cache::VecCache<rustc_hir[d33cae78527aecc7]::hir_id::OwnerId, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 8usize]>, rustc_query_system[e1590dd222ee792c]::dep_graph::graph::DepNodeIndex>, false, false, false>, rustc_query_impl[4198737f17c2ba68]::plumbing::QueryCtxt, false>
  49:        0x116ee14f8 - rustc_query_impl[4198737f17c2ba68]::query_impl::mir_drops_elaborated_and_const_checked::get_query_non_incr::__rust_end_short_backtrace
  50:        0x115f05b76 - <rustc_middle[a14ca4759a2c046f]::ty::context::TyCtxt>::par_hir_body_owners::<rustc_interface[f99dd79e9a35495f]::passes::run_required_analyses::{closure#3}::{closure#0}>::{closure#0}
  51:        0x115fa978b - rustc_interface[f99dd79e9a35495f]::passes::run_required_analyses
  52:        0x115fabae3 - rustc_interface[f99dd79e9a35495f]::passes::analysis
  53:        0x116ecb6ea - rustc_query_impl[4198737f17c2ba68]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[4198737f17c2ba68]::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 0usize]>>
  54:        0x116c69d54 - rustc_query_system[e1590dd222ee792c]::query::plumbing::try_execute_query::<rustc_query_impl[4198737f17c2ba68]::DynamicConfig<rustc_query_system[e1590dd222ee792c]::query::caches::SingleCache<rustc_middle[a14ca4759a2c046f]::query::erase::Erased<[u8; 0usize]>>, false, false, false>, rustc_query_impl[4198737f17c2ba68]::plumbing::QueryCtxt, false>
  55:        0x116ed75b5 - rustc_query_impl[4198737f17c2ba68]::query_impl::analysis::get_query_non_incr::__rust_end_short_backtrace
  56:        0x11551eb78 - rustc_interface[f99dd79e9a35495f]::passes::create_and_enter_global_ctxt::<core[c2a971250a84775]::option::Option<rustc_interface[f99dd79e9a35495f]::queries::Linker>, rustc_driver_impl[8c05a4638ee6701e]::run_compiler::{closure#0}::{closure#2}>
  57:        0x115534479 - rustc_interface[f99dd79e9a35495f]::interface::run_compiler::<(), rustc_driver_impl[8c05a4638ee6701e]::run_compiler::{closure#0}>::{closure#1}
  58:        0x11551fe3d - std[e6c9211e353aebe9]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[f99dd79e9a35495f]::util::run_in_thread_with_globals<rustc_interface[f99dd79e9a35495f]::util::run_in_thread_pool_with_globals<rustc_interface[f99dd79e9a35495f]::interface::run_compiler<(), rustc_driver_impl[8c05a4638ee6701e]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  59:        0x115539fcd - <<std[e6c9211e353aebe9]::thread::Builder>::spawn_unchecked_<rustc_interface[f99dd79e9a35495f]::util::run_in_thread_with_globals<rustc_interface[f99dd79e9a35495f]::util::run_in_thread_pool_with_globals<rustc_interface[f99dd79e9a35495f]::interface::run_compiler<(), rustc_driver_impl[8c05a4638ee6701e]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[c2a971250a84775]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  60:        0x117956d4b - std::sys::pal::unix::thread::Thread::new::thread_start::h84c0937bf04c1f94
  61:     0x7ff8030cd253 - __pthread_start


rustc version: 1.87.0-nightly (78948ac25 2025-03-20)
platform: x86_64-apple-darwin

query stack during panic:
#0 [promoted_mir] optimizing promoted MIR for `main`
#1 [eval_to_allocation_raw] const-evaluating + checking `main::promoted[1]`
#2 [eval_to_const_value_raw] simplifying constant for the type system `main::promoted[1]`
#3 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
#4 [analysis] running analysis passes on this crate
end of query stack

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the two cases with cargo build --release --target=i686-unknown-linux-gnu, then trace the constant-evaluation path through compiler/rustc_middle/src/mir/interpret/value.rs and rustc_mir_transform's known_panics_lint, as shown in the report. Done means oversized format_args! strings no longer construct invalid references or cause rustc to ICE.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.