1
0
mirror of https://github.com/golang/go synced 2024-09-29 15:14:28 -06:00
go/test/fixedbugs/issue24491.go
Cuong Manh Le bdb480fd62 cmd/compile: fix mishandling of unsafe-uintptr arguments in go/defer
Currently, the statement:

	go g(uintptr(f()))

gets rewritten into:

	tmp := f()
	newproc(8, g, uintptr(tmp))
	runtime.KeepAlive(tmp)

which doesn't guarantee that tmp is still alive by time the g call is
scheduled to run.

This CL fixes the issue, by wrapping g call in a closure:

	go func(p unsafe.Pointer) {
		g(uintptr(p))
	}(f())

then this will be rewritten into:

	tmp := f()
	go func(p unsafe.Pointer) {
		g(uintptr(p))
		runtime.KeepAlive(p)
	}(tmp)
	runtime.KeepAlive(tmp)  // superfluous, but harmless

So the unsafe.Pointer p will be kept alive at the time g call runs.

Updates #24491

Change-Id: Ic10821251cbb1b0073daec92b82a866c6ebaf567
Reviewed-on: https://go-review.googlesource.com/c/go/+/253457
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-09-09 07:50:01 +00:00

46 lines
799 B
Go

// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This test makes sure unsafe-uintptr arguments are handled correctly.
package main
import (
"runtime"
"unsafe"
)
var done = make(chan bool, 1)
func setup() unsafe.Pointer {
s := "ok"
runtime.SetFinalizer(&s, func(p *string) { *p = "FAIL" })
return unsafe.Pointer(&s)
}
//go:noinline
//go:uintptrescapes
func test(s string, p uintptr) {
runtime.GC()
if *(*string)(unsafe.Pointer(p)) != "ok" {
panic(s + " return unexpected result")
}
done <- true
}
func main() {
test("normal", uintptr(setup()))
<-done
go test("go", uintptr(setup()))
<-done
func() {
defer test("defer", uintptr(setup()))
}()
<-done
}