mirror of https://github.com/golang/go.git
cmd/compile: note escape of parts of closured-capture vars
Missed a case for closure calls (OCALLFUNC && indirect) in esc.go:esccall. Cleanup to runtime code for windows to more thoroughly hide a technical escape. Also made code pickier about failing to late non-optional kernel32.dll. Fixes #14409. Change-Id: Ie75486a2c8626c4583224e02e4872c2875f7bca5 Reviewed-on: https://go-review.googlesource.com/20102 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
eb876dd83c
commit
d8c815d8b5
|
|
@ -1458,6 +1458,11 @@ func esccall(e *EscState, n *Node, up *Node) {
|
|||
if haspointers(t.Type) {
|
||||
escassignSinkNilWhy(e, n, src, "receiver in indirect call")
|
||||
}
|
||||
} else { // indirect and OCALLFUNC = could be captured variables, too. (#14409)
|
||||
ll := e.nodeEscState(n).Escretval.Slice()
|
||||
for _, llN := range ll {
|
||||
escassignDereference(e, llN, fn, e.stepAssign(nil, llN, fn, "captured by called closure"))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,23 +110,28 @@ func asmstdcall(fn unsafe.Pointer)
|
|||
|
||||
var asmstdcallAddr unsafe.Pointer
|
||||
|
||||
func windowsFindfunc(name []byte, lib uintptr) stdFunction {
|
||||
f := stdcall2(_GetProcAddress, lib, uintptr(unsafe.Pointer(&name[0])))
|
||||
return stdFunction(unsafe.Pointer(f))
|
||||
}
|
||||
|
||||
func loadOptionalSyscalls() {
|
||||
var buf [50]byte // large enough for longest string
|
||||
strtoptr := func(s string) uintptr {
|
||||
buf[copy(buf[:], s)] = 0 // nil-terminated for OS
|
||||
return uintptr(noescape(unsafe.Pointer(&buf[0])))
|
||||
}
|
||||
l := stdcall1(_LoadLibraryA, strtoptr("kernel32.dll"))
|
||||
findfunc := func(name string) stdFunction {
|
||||
f := stdcall2(_GetProcAddress, l, strtoptr(name))
|
||||
return stdFunction(unsafe.Pointer(f))
|
||||
}
|
||||
if l != 0 {
|
||||
_AddDllDirectory = findfunc("AddDllDirectory")
|
||||
_AddVectoredContinueHandler = findfunc("AddVectoredContinueHandler")
|
||||
_GetQueuedCompletionStatusEx = findfunc("GetQueuedCompletionStatusEx")
|
||||
_LoadLibraryExW = findfunc("LoadLibraryExW")
|
||||
var (
|
||||
kernel32dll = []byte("kernel32.dll\000")
|
||||
addVectoredContinueHandler = []byte("AddVectoredContinueHandler\000")
|
||||
getQueuedCompletionStatusEx = []byte("GetQueuedCompletionStatusEx\000")
|
||||
addDllDirectory = []byte("AddDllDirectory\000")
|
||||
loadLibraryExW = []byte("LoadLibraryExW\000")
|
||||
)
|
||||
|
||||
k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0])))
|
||||
if k32 == 0 {
|
||||
throw("kernel32.dll not found")
|
||||
}
|
||||
_AddDllDirectory = windowsFindfunc(addDllDirectory, k32)
|
||||
_AddVectoredContinueHandler = windowsFindfunc(addVectoredContinueHandler, k32)
|
||||
_GetQueuedCompletionStatusEx = windowsFindfunc(getQueuedCompletionStatusEx, k32)
|
||||
_LoadLibraryExW = windowsFindfunc(loadLibraryExW, k32)
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
|
|
|
|||
|
|
@ -145,3 +145,29 @@ func ClosureCallArgs15() {
|
|||
// BAD: p should not escape here
|
||||
}(&p) // ERROR "&p escapes to heap" "\(func literal\)\(&p\) escapes to heap"
|
||||
}
|
||||
|
||||
func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
|
||||
t := s + "YYYY" // ERROR "escapes to heap"
|
||||
return ClosureLeak1a(t) // ERROR "ClosureLeak1 ... argument does not escape"
|
||||
}
|
||||
|
||||
// See #14409 -- returning part of captured var leaks it.
|
||||
func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
|
||||
return func() string { // ERROR "ClosureLeak1a func literal does not escape"
|
||||
return a[0]
|
||||
}()
|
||||
}
|
||||
|
||||
func ClosureLeak2(s string) string { // ERROR "ClosureLeak2 s does not escape"
|
||||
t := s + "YYYY" // ERROR "escapes to heap"
|
||||
c := ClosureLeak2a(t) // ERROR "ClosureLeak2 ... argument does not escape"
|
||||
return c
|
||||
}
|
||||
func ClosureLeak2a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
|
||||
return ClosureLeak2b(func() string { // ERROR "ClosureLeak2a func literal does not escape"
|
||||
return a[0]
|
||||
})
|
||||
}
|
||||
func ClosureLeak2b(f func() string) string { // ERROR "leaking param: f to result ~r1 level=1"
|
||||
return f()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue