T66: cmd doubles the backslashes ending a dropped path, since a program's parser reads one before the closing quote as a quote, as C:\ ends, and a path holding !, which cmd expands inside quotes under /v:on, stops the drop

This commit is contained in:
ZacharyZhang-NY committed 2026-10-19 16:59:47 -04:00
1 parent ac5e17af76
commit 566056257f
4 files changed
+19 -9

No files matched your search

+6 -4
View File
@@ -20,7 +20,7 @@ pub enum Quote {
Posix,
/// Single quotes, which expand nothing.
PowerShell,
/// Double quotes, past which cmd still expands `%`.
/// Double quotes, past which cmd still expands `%` and, under `/v:on`, `!`.
Cmd,
}
@@ -55,10 +55,12 @@ pub fn typed(paths: &[PathBuf], quote: Quote) -> anyhow::Result<String> {
}
Quote::Cmd => {
anyhow::ensure!(
!text.contains(['%', '"']),
"{text:?} holds % or \", which cmd reads inside quotes"
!text.contains(['%', '!', '"']),
"{text:?} holds %, ! or \", which cmd reads inside quotes"
);
out = format!("\"{text}\"");
// A program reads a backslash before the closing quote as a quote.
let trailing = text.len() - text.trim_end_matches('\\').len();
out = format!("\"{text}{}\"", "\\".repeat(trailing));
}
}
out.push(' ');
+11 -3
View File
@@ -40,14 +40,22 @@ fn a_powershell_path_is_single_quoted_with_its_quotes_doubled() {
}
#[test]
fn a_cmd_path_is_double_quoted_and_one_with_a_percent_types_nothing() {
fn a_cmd_path_is_double_quoted_its_trailing_backslashes_doubled_and_one_cmd_expands_types_nothing()
{
let typed = |all: &[&str]| typed_as(Quote::Cmd, all);
assert_eq!(
typed(&["C:\\My Files\\a&b^c.txt", "D:\\c"]),
"\"C:\\My Files\\a&b^c.txt\" \"D:\\c\" "
);
let percent = super::typed(&[PathBuf::from("C:\\%PATH%.txt")], Quote::Cmd);
assert!(percent.is_err(), "{percent:?}");
assert_eq!(
typed(&["C:\\", "D:\\clip.mp4"]),
"\"C:\\\\\" \"D:\\clip.mp4\" ",
"a root's backslash"
);
for name in ["C:\\%PATH%.txt", "C:\\!DROP!.txt"] {
let refused = super::typed(&[PathBuf::from(name)], Quote::Cmd);
assert!(refused.is_err(), "{name}: {refused:?}");
}
}
#[test]