Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broken quote handling when spawning a process from a cmd script. #91991

Closed
mwu-tow opened this issue Dec 16, 2021 · 3 comments · Fixed by #92208
Closed

Broken quote handling when spawning a process from a cmd script. #91991

mwu-tow opened this issue Dec 16, 2021 · 3 comments · Fixed by #92208
Labels
C-bug Category: This is a bug. O-windows Operating system: Windows P-high High priority regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@mwu-tow
Copy link

mwu-tow commented Dec 16, 2021

Code

I tried this code:

pub fn greet(script_path: &std::path::Path, name: &str) -> std::io::Result<std::process::ExitStatus> {
    std::process::Command::new(script_path)
        .arg(name)
        .spawn()?
        .wait()
}

pub fn main() -> std::io::Result<()> {
    let script_path = std::env::temp_dir().join("hello.cmd");
    std::fs::write(&script_path, "@echo Hello, %~1!")?;
    greet(&script_path, "world")?;
    greet(&script_path, "fellow Rustaceans")?;
    Ok(())
}

I expected to see this happen:

Hello, world!
Hello, fellow Rustaceans!

Instead, this happened:

Hello, world!
'C:\Users\mwurb\AppData\Local\Temp\hello.cmd" "fellow' is not recognized as an internal or external command,
operable program or batch file.

This is caused by different quote handling.
The first (correct) command line for the spawned process (as observed by procmon) is:

C:\WINDOWS\system32\cmd.exe /c ""C:\Users\mwurb\AppData\Local\Temp\hello.cmd" "fellow Rustaceans""

The broken one is:

C:\WINDOWS\system32\cmd.exe /c "C:\Users\mwurb\AppData\Local\Temp\hello.cmd" "fellow Rustaceans"

The command for cmd must be in additional set of quotes, as the first and last one are stripped.
It works when there are no spaces in the arguments due to the exception rule, see https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd#remarks

Version it worked on

Stable. It worked up until nightly-2021-11-20

rustc 1.58.0-nightly (a77da2d45 2021-11-19)
binary: rustc
commit-hash: a77da2d454e6caa227a85b16410b95f93495e7e0
commit-date: 2021-11-19
host: x86_64-pc-windows-msvc
release: 1.58.0-nightly
LLVM version: 13.0.0     

Version with regression

nightly-2021-11-21

rustc 1.58.0-nightly (2885c4748 2021-11-20)
binary: rustc
commit-hash: 2885c474823637ae69c5967327327a337aebedb2
commit-date: 2021-11-20
host: x86_64-pc-windows-msvc
release: 1.58.0-nightly
LLVM version: 13.0.0

@rustbot modify labels: +regression-from-stable-to-nightly -regression-untriaged

@mwu-tow mwu-tow added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Dec 16, 2021
@rustbot rustbot added regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. I-prioritize Issue: Indicates that prioritization has been requested for this issue. and removed regression-untriaged Untriaged performance or correctness regression. labels Dec 16, 2021
@jyn514 jyn514 added O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 16, 2021
@ChrisDenton
Copy link
Member

This is caused by Rust now handling finding the exe to run itself (for security reasons). The fix here would be. as you say, to detect .cmd or .bat extensions and add the extra quotes.

Technical details

The underlying function call here is CreateProcessW. As the documentation says, this can only be used to run .exe files.

To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.

However, an undocumented feature of CreateProcessW is that it will do this for us if given a .bat or .cmd file. Previously we used to leave the lpApplicationName argument blank and let it guess the right application from the lpCommandLine argument. So apparently it would fill in cmd.exe for the application name and add /c plus the extra quotes to lpCommandLine. But now that we do fill in the lpApplicationName ourselves, it will still change lpApplicationName to cmd.exe and add /c to lpCommandLine but evidentially doesn't add the extra quotes. Thus we need to do this ourselves.

@m-ou-se m-ou-se added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Dec 22, 2021
@joshtriplett
Copy link
Member

@ChrisDenton That seems reasonable; could you or someone on the Windows team submit a PR adding the requisite quoting (since quoting is hard to get right)?

@ChrisDenton
Copy link
Member

Oops, sorry! I had a PR lined up but forgot to submit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. O-windows Operating system: Windows P-high High priority regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants