Fix println! ICE when parsing percent prefix number

This commit is contained in:
wuaoxiang 2024-05-18 01:05:56 +00:00
parent be7549f82c
commit 582fd1fb53
3 changed files with 49 additions and 9 deletions

View File

@ -263,13 +263,13 @@ pub enum Num {
} }
impl Num { 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 { 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 == "*" { } else if s == "*" {
Num::Next Some(Num::Next)
} else { } 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 @@ macro_rules! move_to {
state = Prec; state = Prec;
parameter = None; parameter = None;
flags = ""; 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); move_to!(end);
} }
// It's invalid, is what it is. // It's invalid, is what it is.
@ -452,7 +455,10 @@ macro_rules! move_to {
'1'..='9' => { '1'..='9' => {
let end = at_next_cp_while(next, char::is_ascii_digit); let end = at_next_cp_while(next, char::is_ascii_digit);
state = Prec; 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); move_to!(end);
} }
_ => { _ => {
@ -468,7 +474,7 @@ macro_rules! move_to {
match end.next_cp() { match end.next_cp() {
Some(('$', end2)) => { Some(('$', end2)) => {
state = Prec; state = Prec;
width = Some(Num::from_str("", Some(at.slice_between(end).unwrap()))); width = Num::from_str("", at.slice_between(end));
move_to!(end2); move_to!(end2);
} }
_ => { _ => {
@ -500,7 +506,7 @@ macro_rules! move_to {
match end.next_cp() { match end.next_cp() {
Some(('$', end2)) => { Some(('$', end2)) => {
state = Length; state = Length;
precision = Some(Num::from_str("*", next.slice_between(end))); precision = Num::from_str("*", next.slice_between(end));
move_to!(end2); move_to!(end2);
} }
_ => { _ => {
@ -513,7 +519,7 @@ macro_rules! move_to {
'0'..='9' => { '0'..='9' => {
let end = at_next_cp_while(next, char::is_ascii_digit); let end = at_next_cp_while(next, char::is_ascii_digit);
state = Length; 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); move_to!(end);
} }
_ => return fallback(), _ => return fallback(),

View File

@ -0,0 +1,6 @@
fn main() {
println!("%100000", 1);
//~^ ERROR argument never used
println!("% 65536", 1);
//~^ ERROR argument never used
}

View File

@ -0,0 +1,28 @@
error: argument never used
--> $DIR/println-percent-prefix-num-issue-125002.rs:2:25
|
LL | println!("%100000", 1);
| ^ argument never used
|
note: format specifiers use curly braces, and the conversion specifier `1` is unknown or unsupported
--> $DIR/println-percent-prefix-num-issue-125002.rs:2:15
|
LL | println!("%100000", 1);
| ^^
= note: printf formatting is not supported; see the documentation for `std::fmt`
error: argument never used
--> $DIR/println-percent-prefix-num-issue-125002.rs:4:29
|
LL | println!("% 65536", 1);
| ^ argument never used
|
note: format specifiers use curly braces, and the conversion specifier ` ` is unknown or unsupported
--> $DIR/println-percent-prefix-num-issue-125002.rs:4:15
|
LL | println!("% 65536", 1);
| ^^
= note: printf formatting is not supported; see the documentation for `std::fmt`
error: aborting due to 2 previous errors