Demonstrate that shell metacharacters are mangled on Windows

On Windows, NewShell escapes shell metacharacters (`&`, `|`, `<`, `>`,
`%`) with `^` and splits the command into separate arguments. The
operators in a custom command therefore never reach cmd as operators,
so command chaining (`&&`), pipes, redirection and `%VAR%` expansion all
silently break (#2427, #4147, #5113; the stray `^` is also what #3092
reports).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller 2026-06-16 11:55:54 +02:00
parent 41efc9a37a
commit e0fcdf1c3f

View file

@ -83,6 +83,24 @@ func TestOSCommandQuoteWindows(t *testing.T) {
assert.EqualValues(t, expected, actual)
}
// On Windows, NewShell must hand the command to cmd.exe verbatim.
func TestNewShellWindowsPassesMetacharactersVerbatim(t *testing.T) {
osCommand := NewDummyOSCommand()
platform := &Platform{OS: "windows", Shell: "cmd", ShellArg: "/c"}
osCommand.Platform = platform
osCommand.Cmd.platform = platform
command := `echo a && echo b | sort > out.txt < in.txt %PATH%`
assert.Equal(t,
/* EXPECTED:
[]string{"cmd", "/s", "/c", command},
ACTUAL: */
[]string{"cmd", "/c", "echo", "a", "^&^&", "echo", "b", "^|", "sort", "^>", "out.txt", "^<", "in.txt", "^%PATH^%"},
osCommand.Cmd.NewShell(command, "").Args(),
)
}
func TestOSCommandFileType(t *testing.T) {
type scenario struct {
path string