Skip to content

Commit e6b462c

Browse files
committed
Fix println! ICE when parsing percent prefix number
1 parent be7549f commit e6b462c

File tree

3 files changed

+51
-9
lines changed

3 files changed

+51
-9
lines changed

Diff for: compiler/rustc_builtin_macros/src/format_foreign.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,15 @@ pub(crate) mod printf {
263263
}
264264

265265
impl Num {
266-
fn from_str(s: &str, arg: Option<&str>) -> Self {
266+
fn from_str(s: &str, arg: Option<&str>) -> Option<Self> {
267267
if let Some(arg) = arg {
268-
Num::Arg(arg.parse().unwrap_or_else(|_| panic!("invalid format arg `{arg:?}`")))
268+
Some(Num::Arg(
269+
arg.parse().unwrap_or_else(|_| panic!("invalid format arg `{arg:?}`")),
270+
))
269271
} else if s == "*" {
270-
Num::Next
272+
Some(Num::Next)
271273
} else {
272-
Num::Num(s.parse().unwrap_or_else(|_| panic!("invalid format num `{s:?}`")))
274+
s.parse().ok().map(|num| Num::Num(num))
273275
}
274276
}
275277

@@ -421,7 +423,10 @@ pub(crate) mod printf {
421423
state = Prec;
422424
parameter = None;
423425
flags = "";
424-
width = Some(Num::from_str(at.slice_between(end).unwrap(), None));
426+
width = Num::from_str(at.slice_between(end).unwrap(), None);
427+
if width.is_none() {
428+
return fallback();
429+
}
425430
move_to!(end);
426431
}
427432
// It's invalid, is what it is.
@@ -452,7 +457,10 @@ pub(crate) mod printf {
452457
'1'..='9' => {
453458
let end = at_next_cp_while(next, char::is_ascii_digit);
454459
state = Prec;
455-
width = Some(Num::from_str(at.slice_between(end).unwrap(), None));
460+
width = Num::from_str(at.slice_between(end).unwrap(), None);
461+
if width.is_none() {
462+
return fallback();
463+
}
456464
move_to!(end);
457465
}
458466
_ => {
@@ -468,7 +476,7 @@ pub(crate) mod printf {
468476
match end.next_cp() {
469477
Some(('$', end2)) => {
470478
state = Prec;
471-
width = Some(Num::from_str("", Some(at.slice_between(end).unwrap())));
479+
width = Some(Num::from_str("", Some(at.slice_between(end).unwrap())).unwrap());
472480
move_to!(end2);
473481
}
474482
_ => {
@@ -500,7 +508,7 @@ pub(crate) mod printf {
500508
match end.next_cp() {
501509
Some(('$', end2)) => {
502510
state = Length;
503-
precision = Some(Num::from_str("*", next.slice_between(end)));
511+
precision = Some(Num::from_str("*", next.slice_between(end)).unwrap());
504512
move_to!(end2);
505513
}
506514
_ => {
@@ -513,7 +521,7 @@ pub(crate) mod printf {
513521
'0'..='9' => {
514522
let end = at_next_cp_while(next, char::is_ascii_digit);
515523
state = Length;
516-
precision = Some(Num::from_str(at.slice_between(end).unwrap(), None));
524+
precision = Some(Num::from_str(at.slice_between(end).unwrap(), None).unwrap());
517525
move_to!(end);
518526
}
519527
_ => return fallback(),

Diff for: tests/ui/macros/issue-125002.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
println!("%100000", 1);
3+
//~^ ERROR argument never used
4+
println!("% 65536", 1);
5+
//~^ ERROR argument never used
6+
}

Diff for: tests/ui/macros/issue-125002.stderr

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: argument never used
2+
--> $DIR/issue-125002.rs:2:25
3+
|
4+
LL | println!("%100000", 1);
5+
| ^ argument never used
6+
|
7+
note: format specifiers use curly braces, and the conversion specifier `1` is unknown or unsupported
8+
--> $DIR/issue-125002.rs:2:15
9+
|
10+
LL | println!("%100000", 1);
11+
| ^^
12+
= note: printf formatting is not supported; see the documentation for `std::fmt`
13+
14+
error: argument never used
15+
--> $DIR/issue-125002.rs:4:29
16+
|
17+
LL | println!("% 65536", 1);
18+
| ^ argument never used
19+
|
20+
note: format specifiers use curly braces, and the conversion specifier ` ` is unknown or unsupported
21+
--> $DIR/issue-125002.rs:4:15
22+
|
23+
LL | println!("% 65536", 1);
24+
| ^^
25+
= note: printf formatting is not supported; see the documentation for `std::fmt`
26+
27+
error: aborting due to 2 previous errors
28+

0 commit comments

Comments
 (0)