Skip to content

Commit 7edc434

Browse files
committed
Account for \xFF and \u{FF} sequences in string format errors
1 parent 433ef82 commit 7edc434

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

src/libsyntax_ext/format.rs

+45
Original file line numberDiff line numberDiff line change
@@ -808,12 +808,57 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
808808
}
809809
('\\', Some((next_pos, 'n'))) |
810810
('\\', Some((next_pos, 't'))) |
811+
('\\', Some((next_pos, '0'))) |
811812
('\\', Some((next_pos, '\\'))) |
812813
('\\', Some((next_pos, '\''))) |
813814
('\\', Some((next_pos, '\"'))) => {
814815
skips.push(*next_pos);
815816
let _ = s.next();
816817
}
818+
('\\', Some((_, 'x'))) if !is_raw => {
819+
for _ in 0..3 { // consume `\xAB` literal
820+
if let Some((pos, _)) = s.next() {
821+
skips.push(pos);
822+
} else {
823+
break;
824+
}
825+
}
826+
}
827+
('\\', Some((_, 'u'))) if !is_raw => {
828+
if let Some((pos, _)) = s.next() {
829+
skips.push(pos);
830+
}
831+
if let Some((next_pos, next_c)) = s.next() {
832+
if next_c == '{' {
833+
skips.push(next_pos);
834+
let mut i = 0; // consume up to 6 hexanumeric chars + closing `}`
835+
while let (Some((next_pos, c)), true) = (s.next(), i < 7) {
836+
if c.is_digit(16) {
837+
skips.push(next_pos);
838+
} else if c == '}' {
839+
skips.push(next_pos);
840+
break;
841+
} else {
842+
break;
843+
}
844+
i += 1;
845+
}
846+
} else if next_c.is_digit(16) {
847+
skips.push(next_pos);
848+
// We suggest adding `{` and `}` when appropriate, accept it here as if it
849+
// were correct
850+
let mut i = 0; // consume up to 6 hexanumeric chars
851+
while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
852+
if c.is_digit(16) {
853+
skips.push(next_pos);
854+
} else {
855+
break;
856+
}
857+
i += 1;
858+
}
859+
}
860+
}
861+
}
817862
_ if eat_ws => { // `take_while(|c| c.is_whitespace())`
818863
eat_ws = false;
819864
}

src/test/ui/fmt/format-string-error-2.rs

+15
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,19 @@ raw { \n
6969
//~^^ ERROR invalid format string
7070
println!("\t{}");
7171
//~^ ERROR 1 positional argument in format string
72+
73+
// note: `\x7B` is `{`
74+
println!("\x7B}\u{8} {", 1);
75+
//~^ ERROR invalid format string: expected `'}'` but string was terminated
76+
77+
println!("\x7B}\u8 {", 1);
78+
//~^ ERROR incorrect unicode escape sequence
79+
//~| ERROR argument never used
80+
81+
// note: raw strings don't escape `\xFF` and `\u{FF}` sequences
82+
println!(r#"\x7B}\u{8} {"#, 1);
83+
//~^ ERROR invalid format string: unmatched `}` found
84+
85+
println!(r#"\x7B}\u8 {"#, 1);
86+
//~^ ERROR invalid format string: unmatched `}` found
7287
}

src/test/ui/fmt/format-string-error-2.stderr

+47-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: incorrect unicode escape sequence
2+
--> $DIR/format-string-error-2.rs:77:20
3+
|
4+
LL | println!("/x7B}/u8 {", 1);
5+
| ^^
6+
|
7+
help: format of unicode escape sequences is `/u{…}`
8+
--> $DIR/format-string-error-2.rs:77:20
9+
|
10+
LL | println!("/x7B}/u8 {", 1);
11+
| ^^
12+
113
error: invalid format string: expected `'}'`, found `'a'`
214
--> $DIR/format-string-error-2.rs:5:5
315
|
@@ -139,5 +151,39 @@ error: 1 positional argument in format string, but no arguments were given
139151
LL | println!("/t{}");
140152
| ^^
141153

142-
error: aborting due to 14 previous errors
154+
error: invalid format string: expected `'}'` but string was terminated
155+
--> $DIR/format-string-error-2.rs:74:27
156+
|
157+
LL | println!("/x7B}/u{8} {", 1);
158+
| -^ expected `'}'` in format string
159+
| |
160+
| because of this opening brace
161+
|
162+
= note: if you intended to print `{`, you can escape it using `{{`
163+
164+
error: argument never used
165+
--> $DIR/format-string-error-2.rs:77:28
166+
|
167+
LL | println!("/x7B}/u8 {", 1);
168+
| ------------ ^ argument never used
169+
| |
170+
| formatting specifier missing
171+
172+
error: invalid format string: unmatched `}` found
173+
--> $DIR/format-string-error-2.rs:82:21
174+
|
175+
LL | println!(r#"/x7B}/u{8} {"#, 1);
176+
| ^ unmatched `}` in format string
177+
|
178+
= note: if you intended to print `}`, you can escape it using `}}`
179+
180+
error: invalid format string: unmatched `}` found
181+
--> $DIR/format-string-error-2.rs:85:21
182+
|
183+
LL | println!(r#"/x7B}/u8 {"#, 1);
184+
| ^ unmatched `}` in format string
185+
|
186+
= note: if you intended to print `}`, you can escape it using `}}`
187+
188+
error: aborting due to 19 previous errors
143189

0 commit comments

Comments
 (0)