CmdShell: quote items that cmd.exe would otherwise interpret - #434
Conversation
|
For reviewers: how plexus-utils handles the same problem, since its Behaviour. plexus-utils Reported there, never fixed by quoting. #37 (asterisk in a password) has been open since 2018; #36 (embedded double quote) was closed as its duplicate. The maintainers' direction is architectural: PR #109 drops the What this PR shares with plexus-utils, on purpose. An embedded Follow-up, separate from this PR. plexus-utils runs This comment was created with AI assistance. |
CmdShell wraps the whole command line in one pair of quotes but never quoted the items inside it, so an executable path with parentheses or an argument with & was parsed by cmd.exe as operators. Items containing whitespace or one of the characters cmd.exe /? lists as special are now double-quoted; already-quoted items are left alone. Master had also lost the space quoting that 3.4.2 ships: ef89c5a removed the quoteAndEscape path from Shell and left the trigger hook dead. That hook is removed and the behaviour lives in CmdShell. Fixes #268
b2dfc08 to
dce8d10
Compare
CmdShellbuilds onecmd.exe /X /C "<line>"string and never quoted the items inside it, so an executable path with parentheses or an argument with&was parsed bycmd.exeas operators. This addsCmdShell.quoteOneItem: an item that contains whitespace or one of the characterscmd.exe /?lists as special (& < > ( ) @ ^ |) is wrapped in double quotes; an item already wrapped in double quotes is left alone;setQuotedArgumentsEnabled(false)andsetUnconditionalQuoting(true)keep their meaning.Two things differ from the earlier attempts (#40, MSHARED-851). The quoting is conditional on the documented character set rather than unconditional, and it is confined to
CmdShell, soBourneShellis untouched. It also restores something master lost in ef89c5a (#369): before that commitShell.quoteOneItemdouble-quoted items containing a space throughquoteAndEscape, and 3.4.2 still ships that behaviour.Shell.getQuotingTriggerCharswas the dead remainder of that mechanism and is removed here.Two behaviour changes to be aware of:
^&workaround from [MSHARED-765] Password not escaped (on windows?) #268 stops working.^&contains&, so it is now quoted, and^is literal inside quotes, so the program receives^&. Users who applied it must drop it.-Djdk.lang.Process.allowAmbiguousCommands=false, Java rejects a quoted argument that contains further quotes. Previously only caller-supplied inner quotes could trigger that; now any space or special character does. Default JVMs are unaffected.CmdShellTestpins the string shape on every platform. Two tests inCommandLineUtilsTestrun only on Windows and execute a realcmd.exe:echo a&bmust print"a&b"rather than runb, and a script under alol(1)directory must run. The three windows-latest CI jobs are the evidence for those.Fixes #268, which also covers the parentheses case from #286.
Verified:
mvn -B verifyon JDK 17 (macOS) -> Tests run: 800, Failures: 0, Errors: 0, Skipped: 19; spotless clean; the Windows execution tests pass on all three windows-latest jobs (JDK 8, 21, 25).This change was created with AI assistance.