diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index df22d79f82e8..1394993abade 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -740,20 +740,40 @@ impl<'a> Parser<'a> { word } - /// Optionally parses an integer at the current position. This doesn't deal - /// with overflow at all, it's just accumulating digits. fn integer(&mut self) -> Option { - let mut cur = 0; + let mut cur: usize = 0; let mut found = false; + let mut overflow = false; + let start = self.current_pos(); while let Some(&(_, c)) = self.cur.peek() { if let Some(i) = c.to_digit(10) { - cur = cur * 10 + i as usize; + let (tmp, mul_overflow) = cur.overflowing_mul(10); + let (tmp, add_overflow) = tmp.overflowing_add(i as usize); + if mul_overflow || add_overflow { + overflow = true; + } + cur = tmp; found = true; self.cur.next(); } else { break; } } + + if overflow { + let end = self.current_pos(); + let overflowed_int = &self.input[start..end]; + self.err( + format!( + "integer `{}` does not fit into the type `usize` whose range is `0..={}`", + overflowed_int, + usize::MAX + ), + "integer out of range for `usize`", + self.span(start, end), + ); + } + if found { Some(cur) } else { None } } diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index 2f8c229c68ff..3f9cb149b53e 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -57,6 +57,21 @@ fn invalid06() { musterr("{:>>>}") } +#[test] +fn invalid_position() { + musterr("{18446744073709551616}"); +} + +#[test] +fn invalid_width() { + musterr("{:18446744073709551616}"); +} + +#[test] +fn invalid_precision() { + musterr("{:.18446744073709551616}"); +} + #[test] fn format_nothing() { same( diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index ed398b56612c..799ce9d5daa8 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -327,7 +327,7 @@ //! - `text` must not contain any `'{'` or `'}'` characters, //! - `ws` is any character for which [`char::is_whitespace`] returns `true`, has no semantic //! meaning and is completely optional, -//! - `integer` is a decimal integer that may contain leading zeroes and +//! - `integer` is a decimal integer that may contain leading zeroes and must fit into an `usize` and //! - `identifier` is an `IDENTIFIER_OR_KEYWORD` (not an `IDENTIFIER`) as defined by the [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html). //! //! # Formatting traits