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

cmd/compile: Program should arguably panic, but doesn't #39122

Closed
Merovius opened this issue May 17, 2020 · 2 comments
Closed

cmd/compile: Program should arguably panic, but doesn't #39122

Merovius opened this issue May 17, 2020 · 2 comments

Comments

@Merovius
Copy link
Contributor

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

$ go version
go version go1.14.3 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
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/mero/.cache/go-build"
GOENV="/home/mero/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/mero"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/mero/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/mero/go/pkg/tool/linux_amd64"
GCCGO="/usr/bin/gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build637886539=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I used unsafe to create a []int with len/cap 1 and data pointing at 0:

Program 1

func main() {
	x := *(*[]int)(unsafe.Pointer(&reflect.SliceHeader{Len: 1, Cap: 1}))
	p := &x[0]
	fmt.Println(p, p == nil, interface{}(p) == (*int)(nil))
}

Program 2

func main() {
	x := *(*[]int)(unsafe.Pointer(&reflect.SliceHeader{Len: 1, Cap: 1}))
	p := x[0]
	fmt.Println(p)
}

What did you expect to see?

According to the spec, both programs should panic:

If the evaluation of x would cause a run-time panic, then the evaluation of &x does too.

What did you see instead?

Only Program 2 panics. Also, even though p is nil in Program 1, comparing it to nil evaluates to false. I assume this is due to the compiler seeing how p is initialized and optimizing the comparison out - if you pass it through interface{}, the comparison ends up returning true (presumably fooling this optimization).

Now, arguably it is fine to violate the spec in this case, as we're using unsafe to trick the compiler. I haven't tested if something similar happens if we'd, say, create a PROT_NONE mapping and do the same addressing (I assume it does, though). I just wanted to tell you about it after I found it.

@randall77
Copy link
Contributor

I used unsafe to create a []int with len/cap 1 and data pointing at 0:

That's not a legal slice. The compiler/runtime assume that a slice with a nonzero length has a non-nil data pointer.

Using unsafe you can always put the system into a weird state it wasn't prepared for. For example, a string with a negative length. Users of unsafe need to be prepared for all kinds of restrictions (that aren't specified anywhere).

I'm going to close this issue. I don't see anything actionable here. Unless you are proposing we remove optimizations to handle weird unsafe cases like this?

I haven't tested if something similar happens if we'd, say, create a PROT_NONE mapping and do the same addressing (I assume it does, though).

The spec makes no promises about non-zero faulting pointers. We currently crash (not panic) if we dereference one.

@Merovius
Copy link
Contributor Author

That's fine :) I expected pretty much exactly this, I just wanted to make sure.

@golang golang locked and limited conversation to collaborators May 17, 2021
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

3 participants