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: unsafe.SliceData incoherent resuilt with nil argument #59293

Closed
lboulard opened this issue Mar 28, 2023 · 4 comments
Closed

cmd/compile: unsafe.SliceData incoherent resuilt with nil argument #59293

lboulard opened this issue Mar 28, 2023 · 4 comments
Assignees
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@lboulard
Copy link

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

$ go version
go version go1.20.2 windows/amd64

Does this issue reproduce with the latest release?

Also tested with go1.21 and go-dev using Go playground.

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

go env
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\lboulard\AppData\Local\go-build
set GOENV=C:\Users\lboulard\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\lboulard\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\lboulard\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.20.2
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=NUL
set GOWORK=
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=C:\Users\lboulard\AppData\Local\Temp\go-build1167216644=/tmp/go-build -gno-record-gcc-switches

What did you do?

Trying to understands behavior of unsafe.SliceData() API with simple example.

https://go.dev/play/p/9HKvgvSWqH3

package main

import (
	"fmt"
	"unsafe"
)

func t(buf []byte) {
	start := unsafe.SliceData(buf)
	end := unsafe.Add(unsafe.Pointer(start), cap(buf))
	fmt.Printf(
		"start=%-13v  len=%5v  cap=%5v  end=%-13v  (start == nil) is %-5v, (end == nil) is %-5v, (buf == nil) is %-5v\n",
		start, len(buf), cap(buf), end, start == nil, end == nil, buf == nil,
	)
}

func main() {
	data := make([]byte, 64<<10)
	t(data)
	t(data[32768 : 32768+32])
	t(data[cap(data)-16:])
	t(data[cap(data)-1:])
	t(data[cap(data):])
	t(nil)
}

What did you expect to see?

Expected to have a nil as output of unsafe.SliceData() as documented in Go 1.20.
And, that comparison of this output to nil to be true.

What did you see instead?

Seems to have nil as output of unsafe.SliceData() but comparison to nil is false.

start=0xc000100000   len=65536  cap=65536  end=0xc000110000   (start == nil) is false, (end == nil) is false, (buf == nil) is false
start=0xc000108000   len=   32  cap=32768  end=0xc000110000   (start == nil) is false, (end == nil) is false, (buf == nil) is false
start=0xc00010fff0   len=   16  cap=   16  end=0xc000110000   (start == nil) is false, (end == nil) is false, (buf == nil) is false
start=0xc00010ffff   len=    1  cap=    1  end=0xc000110000   (start == nil) is false, (end == nil) is false, (buf == nil) is false
start=0xc000100000   len=    0  cap=    0  end=0xc000100000   (start == nil) is false, (end == nil) is false, (buf == nil) is false
start=<nil>          len=    0  cap=    0  end=<nil>          (start == nil) is false, (end == nil) is false, (buf == nil) is true 

Program exited.

In example, unsafe.Pointer(start) with start set to nil is expected to be undefined as per documentation.
But start := unsafe.SliceData(buf) with buf set to nil is documented to return nil.
And, I see nil when printing start. But start == nil is returning false!

I am confused. Is it a bug, an documentation error, or, is my understanding incorrect?

@randall77
Copy link
Contributor

Looks like a bug to me. The optimizer is assuming slice pointers are not nil somewhere, and that's wrong given unsafe.SliceData.

@randall77 randall77 self-assigned this Mar 28, 2023
@randall77 randall77 added this to the Go1.21 milestone Mar 28, 2023
@randall77
Copy link
Contributor

@gopherbot, please open a backport issue for 1.20.

This is an incorrect optimizer result. I guess it is possible to work around it, but it can be tricky to fight the optimizer like this.

@gopherbot
Copy link

Backport issue(s) opened: #59296 (for 1.20).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases.

@gopherbot
Copy link

Change https://go.dev/cl/479896 mentions this issue: cmd/compile: don't assume pointer of a slice is nil

@seankhliao seankhliao changed the title affected/package: unsafe.SliceData incoherent resuilt with nil argument cmd/compile: unsafe.SliceData incoherent resuilt with nil argument Mar 28, 2023
@dmitshur dmitshur added the NeedsFix The path to resolution is known, but the work has not been done. label Mar 29, 2023
@golang golang locked and limited conversation to collaborators Mar 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

4 participants