-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
What version of Go are you using (go version)?
$ go version go1.20.2
Does this issue reproduce with the latest release?
no tested yet
What operating system and processor architecture are you using (go env)?
go env Output
$ go envGO111MODULE="on"
GOARCH="arm64"
GOBIN=""
GOCACHE="~/Library/Caches/go-build"
GOENV="~/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="~/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="~/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="~/.g/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="~/.g/go/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.20.2"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="~/Library/Application Support/JetBrains/GoLand2023.1/scratches/go.mod"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/bz/g8kmk1fn0xj0rnprc0v0h33r0000gn/T/go-build1655805848=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
As an apology, although my build env is Mac M1, I cross-compiled the application into the amd64 windows.
So this is a description of the Windows system.
I missed to set my PATH with a empty path, like path1;;path2;
So when I wanted to use exec.Command to open the cmd.exe (my working directory is C:/Windows/System32, just the same as cmd.exe lies), I got aErrDot.
In this situation, I got 2 ways to find the cmd.exe in PATH. The one is to find in the absolute path C:/Windows/System32, and the other one is the empty path which I entered by mistake. And the empty one comes first.
Lines 103 to 139 in 8abc6e2
| if _, found := syscall.Getenv("NoDefaultCurrentDirectoryInExePath"); !found { | |
| if f, err := findExecutable(filepath.Join(".", file), exts); err == nil { | |
| if execerrdot.Value() == "0" { | |
| execerrdot.IncNonDefault() | |
| return f, nil | |
| } | |
| dotf, dotErr = f, &Error{file, ErrDot} | |
| } | |
| } | |
| path := os.Getenv("path") | |
| for _, dir := range filepath.SplitList(path) { | |
| if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil { | |
| if dotErr != nil { | |
| // https://go.dev/issue/53536: if we resolved a relative path implicitly, | |
| // and it is the same executable that would be resolved from the explicit %PATH%, | |
| // prefer the explicit name for the executable (and, likely, no error) instead | |
| // of the equivalent implicit name with ErrDot. | |
| // | |
| // Otherwise, return the ErrDot for the implicit path as soon as we find | |
| // out that the explicit one doesn't match. | |
| dotfi, dotfiErr := os.Lstat(dotf) | |
| fi, fiErr := os.Lstat(f) | |
| if dotfiErr != nil || fiErr != nil || !os.SameFile(dotfi, fi) { | |
| return dotf, dotErr | |
| } | |
| } | |
| if !filepath.IsAbs(f) { | |
| if execerrdot.Value() != "0" { | |
| return f, &Error{file, ErrDot} | |
| } | |
| execerrdot.IncNonDefault() | |
| } | |
| return f, nil | |
| } | |
| } |
In line 114, it enters the empty path which is considered as the . path, and finds cmd.exe in this path.
Without a doubt, it is treated as a RELATIVE PATH and returned with an ErrDot.
I know the relative path is forbidden now.
And I think this is similar to the problem mentioned in the #53536, but not exactly the same.
What did you expect to see?
I have to admit that this is my fault to set an empty path by mistake.
But I still wonder whether the logic in this code should be optimized or not.
Provided with my two opinions as below:
-
In the PATH list, skip the empty path or anything like the relative path which will function as the
.path eventually. After all, there is no need to deal with the.path in this code, because it has been dealt with before. -
We can sort the list before range it. Make the absolute paths come before the relative paths.