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

Automatic parameter escaping in syscall.StarProcess on windows is too restrictive #1849

Closed
vanackere opened this issue May 19, 2011 · 6 comments

Comments

@vanackere
Copy link
Contributor

Windows parameters are transmitted as a single string and it is the responsibility of
each program to do it's own parameter parsing.

Microsoft's C startup code (http://msdn.microsoft.com/en-us/library/ms880421) defines a
standard way for C programs to split the command line into separate arguments and go's
syscall.StartProcess does the correct escaping for those cases.

However, some programs - and most notably the cmd.exe shell - do their own command line
parameter parsing. As an example, if passed the following arguments :
  cmd /s /c "cd "C:\Program Files" && dir"
then cmd.exe will parse its arguments as follows :
  /s
  /c
  cd "C:\Program Files" && dir

See http://ss64.com/nt/cmd.html (see section on /C or /K flags which describes the logic
used to process quote (") characters).

The bug is that there is currently no way to prevent escaping of command line parameters
and therefore no way to execute the previous command from syscall.StartProcess because
the double quotes in the last argument are automatically escaped...
@alexbrainman
Copy link
Member

Comment 1:

Perhaps, you could illustrate your point with an example, like:
"This go program .... outputs this .... while I would expect to see ... instead."
Thank you.
Alex

Status changed to WaitingForReply.

@alexbrainman
Copy link
Member

Comment 2:

Owner changed to @alexbrainman.

@vanackere
Copy link
Contributor Author

Comment 3:

The current API does the right thing with C-based windows program that don't directly
access the command line. Therefore I cannot write an example program without extending
the API or it would break valid programs...
All I can say is : there is currently no way to execute the following command :
 cmd.exe /s /c "cd "C:\Program Files" && dir"
(I should also mention that the python subprocess.Popen function allows to pass a string
instead of a command line on windows (http://docs.python.org/library/subprocess.html,
17.1.1) and does not suffer from this restriction.)
A possible alternative that would fix all my cases would be to not apply any escaping
for an argument if it is already enclosed with quotes. I believe this would then
automatically handle both the cmd.exe and Delphi program cases without any API
changes... 
Programs needing explicit escaping then can do the escaping before passing the argument
down to os.StartProces & co. Any opinion ?
Vincent

@vanackere
Copy link
Contributor Author

Comment 4:

Hi,
I'm attaching a sample program that will probably better explains the problem.
I'm also attaching a custom version of syscall/exec_windows.go with a possible
alternative. Any alternative/suggestion welcome (I'm not attached to any particular
solution to this problem, I just need one that works...).
Thanks,
Vincent

Attachments:

  1. issue1849.go (1715 bytes)
  2. exec_windows.go (6809 bytes)

@alexbrainman
Copy link
Member

Comment 5:

Vincent,
You could replace argument list with this:
args_cmd := []string{"cmd", "/c", "cd", `C:\Program Files`, "&&", "dir", "/a", "/b"}
to get your example to work.
But I can see your problem now. I think, in essence, the problem is that cmd.exe (ms
own) and some others don't use syscall.CommandLineToArgv to parse command line into
arguments, but employ some of their own algorithm to do it. Is that a fare description?
If that is the case, then I agree with you, I can't see any other way, but to provide go
users with a way to not use "standard" procedure of encoding arguments into command
line, but to employ their own.
Your proposed change http://golang.org/cl/4548050/ looks simple enough, but
there is too much mystery / magic in it - user needs to remember to put 0 as first char
of parameters it doesn't want to escape. I would rather do something similar to your
original proposal. Perhaps, we could have new field ProcAttr.CmdLine:
type ProcAttr struct {
        Dir        string
        Env        []string
        Files      []int
        HideWindow bool
}       CmdLine    string
where user can specify "command line" encoded and escaped to his / her taste.
syscall.StartProcess will check for ProcAttr.CmdLine not empty and use it, ignoring argv.
Russ, please comment.
Alex

Labels changed: added os-windows, packagechange.

Status changed to Accepted.

@rsc
Copy link
Contributor

rsc commented May 31, 2011

Comment 6:

This issue was closed by revision f18a4e9.

Status changed to Fixed.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants