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

flag: Parse incorrectly interprets quoted path with a trailing slash as having escaped quotes. #16131

Closed
swernli opened this issue Jun 21, 2016 · 4 comments
Milestone

Comments

@swernli
Copy link

swernli commented Jun 21, 2016

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)?
    go version go1.6.2 windows/amd64
  2. What operating system and processor architecture are you using (go env)?
    set GOARCH=amd64
    set GOBIN=
    set GOEXE=.exe
    set GOHOSTARCH=amd64
    set GOHOSTOS=windows
    set GOOS=windows
    set GOPATH=s:\docker
    set GORACE=
    set GOROOT=C:\Go
    set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
    set GO15VENDOREXPERIMENT=1
    set CC=gcc
    set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
    set CXX=g++
    set CGO_ENABLED=1
  3. What did you do?
    using import "flag" and Windows cmd, compile this program into an executable:
    import (
    "flag"
    "fmt"
    )
    func main() {
    flag.Parse()
    fmt.Println(flag.Arg(0))
    }

and then run it using the following argument:
test.exe "c:\test\"

  1. What did you expect to see?
    Either the argument as passed at the cmdline, "c:\test\", or the argument with the quotes stripped, c:\test\.
  2. What did you see instead?
    The program displays c:\test\" because somehow flag.Parse() incorrectly interprets the seconds quote as being escaped.
@swernli
Copy link
Author

swernli commented Jun 21, 2016

@jterry75 FYI

@griesemer griesemer added this to the Go1.8 milestone Jun 21, 2016
@adg
Copy link
Contributor

adg commented Jun 21, 2016

Is there a document somewhere that explains how Windows treats quotes on the command line? I'd like to understand it once and for all.

@adg adg changed the title flags.Parse() incorrectly interprets quoted path with a trailing slash as having escaped quotes. flag: Parse incorrectly interprets quoted path with a trailing slash as having escaped quotes. Jun 21, 2016
@alexbrainman
Copy link
Member

Is there a document somewhere that explains how Windows treats quotes on the command line? I'd like to understand it once and for all.

Most Windows programs call CommandLineToArgvW WinAPI (or similar) to parse input parameters. Go does too. Go also has syscall.EscapeArg to do the opposite - convert []string into command line string. The syscall.EscapeArg doc also has some references.

Some Windows programs use different rules for encoding []string into command line. Most notably cmd.exe and msiexec.exe (see #15566 for details).

Alex

@alexbrainman
Copy link
Member

This is working as expected.

Go does not have its own command line into parameter list converter (not yet). It uses Windows CommandLineToArgvW for that job. And CommandLineToArgvW converts

`test.exe "c:\test\"`

into

 []string{`test.exe`, `c:\test"`}.

See https://msdn.microsoft.com/en-us/library/ms880421 for CommandLineToArgvW rules.

Luckily we also have new CL https://go-review.googlesource.com/#/c/22932 pending, that replaces call into Windows CommandLineToArgvW with a Go code. I just tried adding your command line to the test there https://go-review.googlesource.com/#/c/22932/2/src/os/exec_windows_test.go@32, and the test still pass. I also printed out from the test:

C:\Users\Alex>u:\test -test.v -test.run=Command
=== RUN   TestCommandLineToArgv
--- PASS: TestCommandLineToArgv (0.01s)
        exec_windows_test.go:44: out=["test"]
        exec_windows_test.go:44: out=["test" "a" "b" "c"]
        exec_windows_test.go:44: out=["test" ""]
        exec_windows_test.go:44: out=["test" ""]
        exec_windows_test.go:44: out=["test" "\""]
        exec_windows_test.go:44: out=["test" "" "a"]
        exec_windows_test.go:44: out=["test" "123"]
        exec_windows_test.go:44: out=["test" "\"123\""]
        exec_windows_test.go:44: out=["test" "\"123" "456\""]
        exec_windows_test.go:44: out=["test" "\\"]
        exec_windows_test.go:44: out=["test" "\\\""]
        exec_windows_test.go:44: out=["test" "\\\\\""]
        exec_windows_test.go:44: out=["test" "\\\"x"]
        exec_windows_test.go:44: out=["test" "\"\"\\\""]
        exec_windows_test.go:44: out=["cmd line" "abc"]
        exec_windows_test.go:44: out=["test" "\\\\\"x\"y z"]
        exec_windows_test.go:44: out=["test" "b" "x\ty"]
        exec_windows_test.go:44: out=["test.exe" "c:\\test\""]
PASS

C:\Users\Alex>

As you can see, the last line looks just like output of your program.

Alex

@golang golang locked and limited conversation to collaborators Jun 21, 2017
@rsc rsc unassigned robpike Jun 23, 2022
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

6 participants