Skip to content

Commit 6a209cd

Browse files
authored
Fix escaping problem in write_literal and print_literal lint suggestion (rust-lang#13990)
fix rust-lang#13959 The current implementation of the `write_literal` and `print_literal` lint performs escaping for the second argument of `write!` ,`writeln!`, `print!` and `println!` of the suggestion by first replacing `"` with `\"`, and then replacing `\` with `\\`. Performing these replacements in this order may lead to unnecessary backslashes being added if the original code contains `"` (e.g. `"` -> `\\"`), potentially resulting in a suggestion that causes the code to fail to compile. In the issue mentioned above, it’s suggested to use raw strings as raw strings, but implementing this would require an ad-hoc change to the current implementation, so it has been deferred. (I'll implement this in another PR) changelog: [`write_literal`]: fix incorrect escaping of suggestions changelog: [`print_literal`]: fix incorrect escaping of suggestions
2 parents 9ede32f + 65b95a2 commit 6a209cd

7 files changed

+137
-3
lines changed

clippy_lints/src/write.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
522522

523523
let replacement = match (format_string_is_raw, replace_raw) {
524524
(false, false) => Some(replacement),
525-
(false, true) => Some(replacement.replace('"', "\\\"").replace('\\', "\\\\")),
525+
(false, true) => Some(replacement.replace('\\', "\\\\").replace('"', "\\\"")),
526526
(true, false) => match conservative_unescape(&replacement) {
527527
Ok(unescaped) => Some(unescaped),
528528
Err(UnescapeErr::Lint) => None,

tests/ui/print_literal.fixed

+14
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,17 @@ fn main() {
6666

6767
println!("mixed: {{hello}} {world}");
6868
}
69+
70+
fn issue_13959() {
71+
println!("\"");
72+
println!(
73+
"
74+
foo
75+
\\
76+
\\\\
77+
\"
78+
\\\"
79+
bar
80+
"
81+
);
82+
}

tests/ui/print_literal.rs

+15
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,18 @@ fn main() {
6666

6767
println!("mixed: {} {world}", "{hello}");
6868
}
69+
70+
fn issue_13959() {
71+
println!("{}", r#"""#);
72+
println!(
73+
"{}",
74+
r#"
75+
foo
76+
\
77+
\\
78+
"
79+
\"
80+
bar
81+
"#
82+
);
83+
}

tests/ui/print_literal.stderr

+37-1
Original file line numberDiff line numberDiff line change
@@ -192,5 +192,41 @@ LL - println!("mixed: {} {world}", "{hello}");
192192
LL + println!("mixed: {{hello}} {world}");
193193
|
194194

195-
error: aborting due to 16 previous errors
195+
error: literal with an empty format string
196+
--> tests/ui/print_literal.rs:71:20
197+
|
198+
LL | println!("{}", r#"""#);
199+
| ^^^^^^
200+
|
201+
help: try
202+
|
203+
LL - println!("{}", r#"""#);
204+
LL + println!("\"");
205+
|
206+
207+
error: literal with an empty format string
208+
--> tests/ui/print_literal.rs:74:9
209+
|
210+
LL | / r#"
211+
LL | | foo
212+
LL | | \
213+
LL | | \\
214+
... |
215+
LL | | bar
216+
LL | | "#
217+
| |__^
218+
|
219+
help: try
220+
|
221+
LL ~ "
222+
LL + foo
223+
LL + \\
224+
LL + \\\\
225+
LL + \"
226+
LL + \\\"
227+
LL + bar
228+
LL ~ "
229+
|
230+
231+
error: aborting due to 18 previous errors
196232

tests/ui/write_literal.fixed

+16
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,19 @@ fn main() {
6262
writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
6363
//~^ ERROR: literal with an empty format string
6464
}
65+
66+
fn issue_13959() {
67+
let mut v = Vec::new();
68+
writeln!(v, "\"");
69+
writeln!(
70+
v,
71+
"
72+
foo
73+
\\
74+
\\\\
75+
\"
76+
\\\"
77+
bar
78+
"
79+
);
80+
}

tests/ui/write_literal.rs

+17
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,20 @@ fn main() {
6262
writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
6363
//~^ ERROR: literal with an empty format string
6464
}
65+
66+
fn issue_13959() {
67+
let mut v = Vec::new();
68+
writeln!(v, "{}", r#"""#);
69+
writeln!(
70+
v,
71+
"{}",
72+
r#"
73+
foo
74+
\
75+
\\
76+
"
77+
\"
78+
bar
79+
"#
80+
);
81+
}

tests/ui/write_literal.stderr

+37-1
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,41 @@ LL - writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
144144
LL + writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
145145
|
146146

147-
error: aborting due to 12 previous errors
147+
error: literal with an empty format string
148+
--> tests/ui/write_literal.rs:68:23
149+
|
150+
LL | writeln!(v, "{}", r#"""#);
151+
| ^^^^^^
152+
|
153+
help: try
154+
|
155+
LL - writeln!(v, "{}", r#"""#);
156+
LL + writeln!(v, "\"");
157+
|
158+
159+
error: literal with an empty format string
160+
--> tests/ui/write_literal.rs:72:9
161+
|
162+
LL | / r#"
163+
LL | | foo
164+
LL | | \
165+
LL | | \\
166+
... |
167+
LL | | bar
168+
LL | | "#
169+
| |__^
170+
|
171+
help: try
172+
|
173+
LL ~ "
174+
LL + foo
175+
LL + \\
176+
LL + \\\\
177+
LL + \"
178+
LL + \\\"
179+
LL + bar
180+
LL ~ "
181+
|
182+
183+
error: aborting due to 14 previous errors
148184

0 commit comments

Comments
 (0)