UpperHex formatting might panic #126425
Copy link
Copy link
Closed
Labels
A-panicArea: Panicking machineryArea: Panicking machineryC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.T-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Description
When writing non-panicking code, it is impossible to use the "{:X}" format specifier as the impl core::fmt::UpperHex for usize and similar code might panic. It seems that it is because the GenericRadix::fmt_int method is using slice indexing notation here:
let buf = &buf[curr..];
This seem to be easily avoidable by replacing it with buf.get(curr..) and some error handling.
Reacted by Eric Lagergren
Metadata
Metadata
Assignees
Labels
A-panicArea: Panicking machineryArea: Panicking machineryC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.T-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Activity
zachs18 commentedon Jun 13, 2024
curris initialized tobuf.len(), and is only ever decremented, so as long as the decrements do not overflow,&buf[curr..]cannot panic.bufhas length 128, andcurris decremented exactly once for each digit, so forcurrto overflow would require that the number to be formatted have more that 128 digits in the particular base (2, 8, or 16), which is currently not possible sinceu128is the largest fixed-width integer type, andusize::BITS <= 64on all currently supported platforms.I suppose a
const _: () = assert!(T::BITS <= 128)or similar could be added to this code to ensure that any future platform withusize::BITS > 128would fail to compile unless this code was updated to account for it, (but I imagine there are several other places in the standard library which makes a similar assumption).ZhekaS commentedon Jun 13, 2024
It's OK that it won't panic in practice, but the compiler is unable to prove it, so it is generating the panic code and linking with panic-related functionality which is desirable to avoid. That is, using crates such as no_panics_whatsoever or similar functionality by other means won't work.
veera-sivarajan commentedon Jun 14, 2024
@rustbot label -needs-triage +T-libs +A-panic +C-enhancement
Replace checked slice indexing by unchecked to support panic-free code
clubby789 commentedon Nov 3, 2024
Based on minimizing the code to:
it seems like LLVM should be removing this panic: https://alive2.llvm.org/ce/z/UJHdEr
ericlagergren commentedon Nov 3, 2024
/might/ be related to #127553
ZhekaS commentedon Nov 4, 2024
I think in the original code the compiler might not be able to infer that
currdoes not underflow, as the assumption is that the max T width is 128 bits, but the compiler does not make such an assumption (as @zachs18 mentions above). I wonder if adding the assertion on the width would give it the necessary hint. Need to test it out, as it might be a better solution than replacing byget_unchecked()whatsoeverUpd:
It looks like the trait
Tis bound to (DisplayInt) does not provide any type width information, so for compile-time checks more changes will be required.Replace checked slice indexing by unchecked to support panic-free code
Rollup merge of rust-lang#132473 - ZhekaS:core_fmt_radix_no_panic, r=…
Rollup merge of rust-lang#132473 - ZhekaS:core_fmt_radix_no_panic, r=…
Rollup merge of rust-lang#132473 - ZhekaS:core_fmt_radix_no_panic, r=…
Unrolled build for rust-lang#132473