Skip to content

cmd/cgo: generates code with inappropriate array copy #32579

@DryHumour

Description

@DryHumour

The following code behaves as expected under go1.11 and go.1.11.10 but panics under go1.12 and go1.12.6.

Minor changes to the expression passed to the address-of operator "fix" the behaviour. Debugging and instrumentation show that an "unexpected" pointer is passed to the underlying cgo wrapper and C function; perhaps a heap allocated temporary? The presence of both IndexExpr appear to be necessary to the reproduction of the problem; with only one or the other, it apparently does not reproduce.

The ast.Print() output appears to match between 1.11 and 1.12, but the liveness/opt analysis (gcflags -m -live), parse tree (-W), Go asm (-S), and final object code all differ in various ways. (I currently lack enough experience with Go compiler internals to further interpret the information.)

What did you do?

(Code does not run under Go playground because of Cgo.)

package main

// #include <string.h>
// struct S { unsigned char data[1]; };
import "C"
import "unsafe"

func main() {
	const fill = 0xff
	var s [1]C.struct_S
	C.memset(unsafe.Pointer(&s[0].data[0]), fill, C.size_t(unsafe.Sizeof(s[0].data))) // panic
	// C.memset(unsafe.Pointer(&(s[0].data[0])), fill, C.size_t(unsafe.Sizeof(s[0].data))) // ok
	// C.memset(unsafe.Pointer(&s[0].data), fill, C.size_t(unsafe.Sizeof(s[0].data))) // ok
	if s[0].data[0] != fill {
		panic("oops")
	}
}

What did you expect to see?

No output, exit 0.

With go run -gcflags -r:

# command-line-arguments
MOVE [0xc00038bb30]
.   NAME-main.s a(true) g(1) l(13) x(0) class(PAUTO) ld(1) tc(1) addrtaken used ARRAY-[1]_Ctype_struct_S

What did you see instead?


goroutine 1 [running]:
main.main()
	/home/nschelle/go/src/cgo/cgo.go:15 +0x42
exit status 2

With go run -gcflags -r:

# command-line-arguments
MOVE [0xc0003b73b0]
.   NAME-main._cgoIndex0 a(true) g(2) l(14) x(0) class(PAUTO) ld(1) tc(1) addrtaken used ARRAY-[1]_Ctype_uchar
panic: oops

goroutine 1 [running]:
main.main()
	/home/nschelle/go/src/cgo/cgo.go:15 +0x42
exit status 2

Does this issue reproduce with the latest release (go1.12.6)?

Yes.

System details

go version go1.12.5 linux/amd64
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/nschelle/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/nschelle/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
GOROOT/bin/go version: go version go1.12.5 linux/amd64
GOROOT/bin/go tool compile -V: compile version go1.12.5
uname -sr: Linux 4.4.0-146-generic
Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.6 LTS
Release:	16.04
Codename:	xenial
/gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/libc.so.6: GNU C Library (GNU libc) stable release version 2.28.
gdb --version: GNU gdb (GDB) 8.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions