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: ICE on deferred call to syscall.LazyDLL.Call #44415

Open
NhokCrazy199 opened this issue Feb 19, 2021 · 12 comments
Open

cmd/compile: ICE on deferred call to syscall.LazyDLL.Call #44415

NhokCrazy199 opened this issue Feb 19, 2021 · 12 comments

Comments

@NhokCrazy199
Copy link

@NhokCrazy199 NhokCrazy199 commented Feb 19, 2021

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

go version go1.16 windows/amd64

Does this issue reproduce with the latest release?

Yes, it does

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

set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\MyUser\AppData\Local\go-build
set GOENV=C:\Users\MyUser\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=D:\Workspace\Go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=D:\Workspace\Go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.16
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=D:\Workspace\Go\src\proj-path\go.mod
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\MyUser\AppData\Local\Temp\go-build1529013081=/tmp/go-build -gno-record-gcc-switches

What did you do?

My previous version is Go 1.15.6 and everything is ok.
I updated my Go and my func can not build with the lastest version:

func DPApi(data []byte) ([]byte, error) {
	dllCrypt := syscall.NewLazyDLL("Crypt32.dll")
	dllKernel := syscall.NewLazyDLL("Kernel32.dll")
	procDecryptData := dllCrypt.NewProc("CryptUnprotectData")
	procLocalFree := dllKernel.NewProc("LocalFree")
	var outBlob dataBlob
	r, _, err := procDecryptData.Call(uintptr(unsafe.Pointer(NewBlob(data))), 0, 0, 0, 0, 0, uintptr(unsafe.Pointer(&outBlob)))
	if r == 0 {
		return nil, err
	}
	defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
	return outBlob.ToByteArray(), nil
}

What did you expect to see?

My func can run and build with my Go

What did you see instead?

proj-path/core/browsers/decrypt
core\browsers\decrypt\decrypt_windows.go:89:2: internal compiler error: 'wrap·2': Value live at entry. It shouldn't be. func wrap·2, node procLocalFree, value v35

Please file a bug report including a short program that triggers the error.
https://golang.org/issue/new
core\browsers\decrypt\decrypt_windows.go:75:2: internal compiler error: 'wrap·1': Value live at entry. It shouldn't be. func wrap·1, node procLocalFree, value v35

Please file a bug report including a short program that triggers the error.
https://golang.org/issue/new

Desc:
decrypt_windows.go:89 is line defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
decrypt_windows.go:75 is line func DPApi(data []byte) ([]byte, error) {

@egonelbre
Copy link
Contributor

@egonelbre egonelbre commented Feb 19, 2021

Note that the dll and proc instantiation should probably be outside the function, something like:

var (
	dllCrypt  = syscall.NewLazyDLL("Crypt32.dll")
	dllKernel = syscall.NewLazyDLL("Kernel32.dll")

	procDecryptData = dllCrypt.NewProc("CryptUnprotectData")
	procLocalFree   = dllKernel.NewProc("LocalFree")
)

// chrome < 80 https://chromium.googlesource.com/chromium/src/+/76f496a7235c3432983421402951d73905c8be96/components/os_crypt/os_crypt_win.cc#82
func DPApi(data []byte) ([]byte, error) {
	var outBlob dataBlob
	r, _, err := procDecryptData.Call(uintptr(unsafe.Pointer(NewBlob(data))), 0, 0, 0, 0, 0, uintptr(unsafe.Pointer(&outBlob)))
	if r == 0 {

But, it looks like a compiler bug nevertheless.

@egonelbre
Copy link
Contributor

@egonelbre egonelbre commented Feb 19, 2021

Error message looks the same as #44355.

@toothrot toothrot added the OS-Windows label Feb 19, 2021
@toothrot
Copy link
Contributor

@toothrot toothrot commented Feb 19, 2021

Thanks for the detailed issue. I think you're right that this is a duplicate of #44355. I'll close this in lieu of that issue.

I think this is an interesting case to mention there though.

@mdempsky
Copy link
Member

@mdempsky mdempsky commented Feb 19, 2021

Issue #44355 is pretty narrow: it should only affect inlinable functions that explicitly name all of their result parameters as blank (i.e., _), and then contain a single return statement. Are there any functions like that in consideration here?

It would be great to have a standalone reproducer for this issue. Ideally one that can be built from Linux (e.g., using GOOS=windows is fine, but without requiring cgo).

(FWIW, "Value live at entry" is a pretty generic catch-all failure that happens later in the compiler when almost anything goes wrong in the frontend and we didn't catch it sooner to give a more descriptive error report. So I don't recommend using that alone to deduplicate issues.)

@egonelbre
Copy link
Contributor

@egonelbre egonelbre commented Feb 20, 2021

Windows reproducer (based on the initial cause in https://github.com/moonD4rk/HackBrowserData/blob/6a11361e1dbf0c3e455ccb06a4f31d073f7d8e8e/core/decrypt/decrypt_windows.go):

package decrypt

import (
	"syscall"
	"unsafe"
)

type dataBlob struct {
	cbData uint32
	pbData *byte
}

func (b *dataBlob) ToByteArray() []byte {
	d := make([]byte, b.cbData)
	copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:])
	return d
}

var dllKernel = syscall.NewLazyDLL("Kernel32.dll")

func Call(data []byte) ([]byte, error) {
	procLocalFree := dllKernel.NewProc("LocalFree")
	var outBlob dataBlob
	defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
	return outBlob.ToByteArray(), nil
}
@mdempsky mdempsky changed the title Error when Go call Win API cmd/compile: ICE on deferred call to syscall.LazyDLL.Call Feb 20, 2021
@mdempsky mdempsky added the NeedsFix label Feb 20, 2021
@mdempsky
Copy link
Member

@mdempsky mdempsky commented Feb 20, 2021

Thanks @egonelbre! Further minimized, and confirmed it reproduces on Linux with GOOS=windows:

package decrypt

import (
	"syscall"
	"unsafe"
)

var dllKernel = syscall.NewLazyDLL("Kernel32.dll")

func Call() {
	procLocalFree := dllKernel.NewProc("LocalFree")
	defer procLocalFree.Call(uintptr(unsafe.Pointer(nil)))
}

Notably, it doesn't reproduce with -gcflags=-N.

/cc @cuonglm

@mdempsky
Copy link
Member

@mdempsky mdempsky commented Feb 20, 2021

Oh, in the fix for #24491, we only fixed direct function calls. We forgot that for method calls, there's a receiver argument that needs to be passed through the wrapper function too.

@mdempsky
Copy link
Member

@mdempsky mdempsky commented Feb 20, 2021

@gopherbot Backport to Go 1.16. Compiler crash on valid Windows code that compiled with Go 1.15.

@ALTree
Copy link
Member

@ALTree ALTree commented Feb 20, 2021

@mdempsky I think you have to say "please" or the gopherbot won't listen to you. A somewhat questionable design decision...

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Feb 20, 2021

@gopherbot Please backport to Go 1.16.

Compiler crash on valid Windows code that compiled with Go 1.15.

@gopherbot
Copy link

@gopherbot gopherbot commented Feb 20, 2021

Backport issue(s) opened: #44463 (for 1.15), #44464 (for 1.16).

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

@gopherbot
Copy link

@gopherbot gopherbot commented Feb 21, 2021

Change https://golang.org/cl/294849 mentions this issue: cmd/compile: fix mishandling of unsafe-uintptr arguments with call method in go/defer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants