Skip to content

Commit

Permalink
Fix escaping problem in write_literal and print_literal lint sugg…
Browse files Browse the repository at this point in the history
…estion (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
  • Loading branch information
Centri3 authored Jan 28, 2025
2 parents 9ede32f + 65b95a2 commit 6a209cd
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 3 deletions.
2 changes: 1 addition & 1 deletion clippy_lints/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {

let replacement = match (format_string_is_raw, replace_raw) {
(false, false) => Some(replacement),
(false, true) => Some(replacement.replace('"', "\\\"").replace('\\', "\\\\")),
(false, true) => Some(replacement.replace('\\', "\\\\").replace('"', "\\\"")),
(true, false) => match conservative_unescape(&replacement) {
Ok(unescaped) => Some(unescaped),
Err(UnescapeErr::Lint) => None,
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/print_literal.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,17 @@ fn main() {

println!("mixed: {{hello}} {world}");
}

fn issue_13959() {
println!("\"");
println!(
"
foo
\\
\\\\
\"
\\\"
bar
"
);
}
15 changes: 15 additions & 0 deletions tests/ui/print_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,18 @@ fn main() {

println!("mixed: {} {world}", "{hello}");
}

fn issue_13959() {
println!("{}", r#"""#);
println!(
"{}",
r#"
foo
\
\\
"
\"
bar
"#
);
}
38 changes: 37 additions & 1 deletion tests/ui/print_literal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,41 @@ LL - println!("mixed: {} {world}", "{hello}");
LL + println!("mixed: {{hello}} {world}");
|

error: aborting due to 16 previous errors
error: literal with an empty format string
--> tests/ui/print_literal.rs:71:20
|
LL | println!("{}", r#"""#);
| ^^^^^^
|
help: try
|
LL - println!("{}", r#"""#);
LL + println!("\"");
|

error: literal with an empty format string
--> tests/ui/print_literal.rs:74:9
|
LL | / r#"
LL | | foo
LL | | \
LL | | \\
... |
LL | | bar
LL | | "#
| |__^
|
help: try
|
LL ~ "
LL + foo
LL + \\
LL + \\\\
LL + \"
LL + \\\"
LL + bar
LL ~ "
|

error: aborting due to 18 previous errors

16 changes: 16 additions & 0 deletions tests/ui/write_literal.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,19 @@ fn main() {
writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
//~^ ERROR: literal with an empty format string
}

fn issue_13959() {
let mut v = Vec::new();
writeln!(v, "\"");
writeln!(
v,
"
foo
\\
\\\\
\"
\\\"
bar
"
);
}
17 changes: 17 additions & 0 deletions tests/ui/write_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,20 @@ fn main() {
writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
//~^ ERROR: literal with an empty format string
}

fn issue_13959() {
let mut v = Vec::new();
writeln!(v, "{}", r#"""#);
writeln!(
v,
"{}",
r#"
foo
\
\\
"
\"
bar
"#
);
}
38 changes: 37 additions & 1 deletion tests/ui/write_literal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,41 @@ LL - writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
LL + writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
|

error: aborting due to 12 previous errors
error: literal with an empty format string
--> tests/ui/write_literal.rs:68:23
|
LL | writeln!(v, "{}", r#"""#);
| ^^^^^^
|
help: try
|
LL - writeln!(v, "{}", r#"""#);
LL + writeln!(v, "\"");
|

error: literal with an empty format string
--> tests/ui/write_literal.rs:72:9
|
LL | / r#"
LL | | foo
LL | | \
LL | | \\
... |
LL | | bar
LL | | "#
| |__^
|
help: try
|
LL ~ "
LL + foo
LL + \\
LL + \\\\
LL + \"
LL + \\\"
LL + bar
LL ~ "
|

error: aborting due to 14 previous errors

0 comments on commit 6a209cd

Please sign in to comment.