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: index out of range when argc is 0 #32775

Open
kneht opened this issue Jun 25, 2019 · 11 comments

Comments

Projects
None yet
5 participants
@kneht
Copy link

commented Jun 25, 2019

What version of Go are you using (go version)?

$ go version
go version go1.12.6 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE=""
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH=""
GOPROXY=""
GORACE=""
GOROOT="/usr/lib/go-1.12"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.12/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

When golang compiled binary invoked by execve with 0 arguments like this:

test.cpp code
#include 

int main() {
execve("test.go.out", NULL, NULL);
}

https://play.golang.org/p/zo3YJZTkBu_A

What did you expect to see?

nothing

What did you see instead?

panic: runtime error: index out of range

goroutine 1 [running]:
flag.init.ializers()
/usr/lib/go-1.12/src/flag/flag.go:1009 +0x172

As for documentation, it's sort of guaranteed that os.Args[0] is a program name:
https://golang.org/pkg/os/#pkg-variables

When argc is 0, at least for Linux platform program name can be fetched from procfs(/proc/self/comm), probably here:

argslice = make([]string, argc)
for i := int32(0); i < argc; i++ {
argslice[i] = gostringnocopy(argv_index(argv, i))
}

@robpike

This comment has been minimized.

Copy link
Contributor

commented Jun 25, 2019

Not sure there's anything to fix. That binary compiles and runs fine; it's the caller that's making a mistake: argv should never be empty.

@gregory-m

This comment has been minimized.

Copy link
Contributor

commented Jun 26, 2019

From execve(2) man page:

argv is an array of argument strings passed to the new program. By convention, the first of these strings should contain the filename associated with the file being executed

On Linux, argv can be specified as NULL, which has the same effect as
specifying this argument as a pointer to a list containing a single NULL pointer.
Do not take advantage of this misfeature!
It is nonstandard and nonportable: on most other UNIX systems doing this
will result in an error (EFAULT).

So, I'am also not sure if we need to fix something.

@kneht

This comment has been minimized.

Copy link
Author

commented Jul 1, 2019

I've spotted this issue when my binary was ran by rsyslog.
Documentation looks inconsistent, as argv[0] doesn't have a program name, but whatever is provided to argv[0].
Module flag apparently is not only in charge of parsing args, but also flags when there is no argv[0] by throwing runtime error.
I'm new to golang and don't really have horse in this race, but from what I see at least len(argv) in flag module needs to be checked.

@gregory-m

This comment has been minimized.

Copy link
Contributor

commented Jul 1, 2019

What config was used for rsyslog?

Something like this:

module(load="omprog")
action(type="omprog"
       binary="/pathto/omprog.py --parm1=\"value 1\" --parm2=\"value2\""
       template="RSYSLOG_TraditionalFileFormat")
@kneht

This comment has been minimized.

Copy link
Author

commented Jul 1, 2019

yep, binary was invoked by omprog with no parameters.
like binary="/pathto/omprog.py"

@kneht

This comment has been minimized.

Copy link
Author

commented Jul 1, 2019

It was fixed in latest versions of rsyslog apparently:
rsyslog/rsyslog@8d807e3

mmexternal bugfix: potentially missing argv[0]
This is incorrect and can cause problems with some language, namely go.
@gregory-m

This comment has been minimized.

Copy link
Contributor

commented Jul 1, 2019

I searched Github and found another examples of execve("cmd", NULL, NULL); usage. It defentely not best practice but maybe it good idea to not panic in such case? @ianlancetaylor @robpike

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jul 1, 2019

It seems to me that the C getopt function will also crash in this case. It really doesn't seem worth worrying about.

But I guess if someone sends a patch for 1.14 we can take a look.

@kneht

This comment has been minimized.

Copy link
Author

commented Jul 1, 2019

getopt(0,NULL,NULL) will work as argc is 0 obviously,
I can try to work on patch, but I would need some guidance on where this issue needs to be fixed.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jul 1, 2019

In the initialization of CommandLine in the flag package.

@gopherbot

This comment has been minimized.

Copy link

commented Jul 2, 2019

Change https://golang.org/cl/184637 mentions this issue: flag: handle nil os.Args on CommandLine initialization

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.