This CL tweaks escape analysis to treat unsafe.Pointer(ptr) as an
escaping operation when -d=checkptr is enabled. This allows better
detection of unsafe pointer arithmetic and conversions, because the
runtime checkptr instrumentation can currently only detect object
boundaries for heap objects, not stack objects.
Updates #22218.
Fixes #34959.
Change-Id: I856812cc23582fe4d0d401592583323e95919f28
Reviewed-on: https://go-review.googlesource.com/c/go/+/201781
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
e.discard(max)
case OCONV, OCONVNOP:
- if n.Type.Etype == TUNSAFEPTR && n.Left.Type.Etype == TUINTPTR {
+ if checkPtr(e.curfn) && n.Type.Etype == TUNSAFEPTR && n.Left.Type.IsPtr() {
+ // When -d=checkptr is enabled, treat
+ // conversions to unsafe.Pointer as an
+ // escaping operation. This allows better
+ // runtime instrumentation, since we can more
+ // easily detect object boundaries on the heap
+ // than the stack.
+ e.assignHeap(n.Left, "conversion to unsafe.Pointer", n)
+ } else if n.Type.Etype == TUNSAFEPTR && n.Left.Type.Etype == TUINTPTR {
e.unsafeValue(k, n.Left)
} else {
e.expr(k, n.Left)
case OCONV, OCONVNOP:
n.Left = walkexpr(n.Left, init)
- if n.Op == OCONVNOP && Debug_checkptr != 0 && Curfn.Func.Pragma&NoCheckPtr == 0 {
+ if n.Op == OCONVNOP && checkPtr(Curfn) {
if n.Type.IsPtr() && n.Left.Type.Etype == TUNSAFEPTR { // unsafe.Pointer to *T
n = walkCheckPtrAlignment(n, init)
break
init.Append(mkcall("checkptrArithmetic", nil, init, n, slice))
return n
}
+
+// checkPtr reports whether pointer checking should be enabled for
+// function fn.
+func checkPtr(fn *Node) bool {
+ return Debug_checkptr != 0 && fn.Func.Pragma&NoCheckPtr == 0
+}