diff options
| author | bors <bors@rust-lang.org> | 2024-05-18 08:44:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-05-18 08:44:01 +0000 |
| commit | 1c90b9fe6eac122b4d3965913b3615f47751a4d3 (patch) | |
| tree | f18822d80aba5f4a47965ce7ac9a3fe6d0279269 /compiler | |
| parent | 36c0a6d40fb6aae9c450305085d64e2ba55c6c58 (diff) | |
| parent | 582fd1fb539ddea199dbc238946b00465a20620e (diff) | |
| download | rust-1c90b9fe6eac122b4d3965913b3615f47751a4d3.tar.gz rust-1c90b9fe6eac122b4d3965913b3615f47751a4d3.zip | |
Auto merge of #125004 - pymongo:issue-125002, r=estebank
Fix println! ICE when parsing percent prefix number
This PR fixes #125002 ICE occurring, for example, with `println!("%100000", 1)` or `println!("% 100000", 1)`.
## Test Case/Change Explanation
The return type of `Num::from_str` has been changed to `Option<Self>` to handle errors when parsing large integers fails.
1. The first `println!` in the test case covers the change of the first `Num::from_str` usage in `format_foreign.rs:426`.
2. The second `println!` in the test case covers the change of the second `Num::from_str` usage in line 460.
3. The 3rd to 5th `Num::from_str` usages behave the same as before.
The 3rd usage would cause an ICE when `num > u16::MAX` in the previous version, but this commit does not include a fix for the ICE in `println!("{:100000$}")`. I think we need to emit an error in the compiler and have more discussion in another issue/PR.
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/format_foreign.rs | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index 307e582d65e..bc2c6def68a 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -263,13 +263,13 @@ pub(crate) mod printf { } impl Num { - fn from_str(s: &str, arg: Option<&str>) -> Self { + fn from_str(s: &str, arg: Option<&str>) -> Option<Self> { if let Some(arg) = arg { - Num::Arg(arg.parse().unwrap_or_else(|_| panic!("invalid format arg `{arg:?}`"))) + arg.parse().ok().map(|arg| Num::Arg(arg)) } else if s == "*" { - Num::Next + Some(Num::Next) } else { - Num::Num(s.parse().unwrap_or_else(|_| panic!("invalid format num `{s:?}`"))) + s.parse().ok().map(|num| Num::Num(num)) } } @@ -421,7 +421,10 @@ pub(crate) mod printf { state = Prec; parameter = None; flags = ""; - width = Some(Num::from_str(at.slice_between(end).unwrap(), None)); + width = at.slice_between(end).and_then(|num| Num::from_str(num, None)); + if width.is_none() { + return fallback(); + } move_to!(end); } // It's invalid, is what it is. @@ -452,7 +455,10 @@ pub(crate) mod printf { '1'..='9' => { let end = at_next_cp_while(next, char::is_ascii_digit); state = Prec; - width = Some(Num::from_str(at.slice_between(end).unwrap(), None)); + width = at.slice_between(end).and_then(|num| Num::from_str(num, None)); + if width.is_none() { + return fallback(); + } move_to!(end); } _ => { @@ -468,7 +474,7 @@ pub(crate) mod printf { match end.next_cp() { Some(('$', end2)) => { state = Prec; - width = Some(Num::from_str("", Some(at.slice_between(end).unwrap()))); + width = Num::from_str("", at.slice_between(end)); move_to!(end2); } _ => { @@ -500,7 +506,7 @@ pub(crate) mod printf { match end.next_cp() { Some(('$', end2)) => { state = Length; - precision = Some(Num::from_str("*", next.slice_between(end))); + precision = Num::from_str("*", next.slice_between(end)); move_to!(end2); } _ => { @@ -513,7 +519,7 @@ pub(crate) mod printf { '0'..='9' => { let end = at_next_cp_while(next, char::is_ascii_digit); state = Length; - precision = Some(Num::from_str(at.slice_between(end).unwrap(), None)); + precision = at.slice_between(end).and_then(|num| Num::from_str(num, None)); move_to!(end); } _ => return fallback(), |
