aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mfinal.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2016-10-03 14:45:52 -0400
committerAustin Clements <austin@google.com>2016-10-28 19:13:44 +0000
commitdb56a63547d7ae9f19afd2497c67f717154f9115 (patch)
treefdc21ccb9c4237d59c312556f6b9c0dcce5a47fc /src/runtime/mfinal.go
parentc5e7006540ca949b481a0477d1308e1373dd5c31 (diff)
downloadgo-db56a63547d7ae9f19afd2497c67f717154f9115.tar.gz
go-db56a63547d7ae9f19afd2497c67f717154f9115.zip
runtime: avoid write barriers to uninitialized finalizer frame memory
runfinq allocates a stack frame on the heap for constructing the finalizer function calls and reuses it for each call. However, because the type of this frame is constantly shifting, it tells mallocgc there are no pointers in it and it acts essentially like uninitialized memory between uses. But runfinq uses pointer writes with write barriers to "initialize" this memory, which is not going to be safe with the hybrid barrier, since the hybrid barrier may see a stale pointer left in the "uninitialized" frame. Fix this by zero-initializing the argument values in the frame before writing the argument pointers. Updates #17503. Change-Id: I951c0a2be427eb9082a32d65c4410e6fdef041be Reviewed-on: https://go-review.googlesource.com/31453 Reviewed-by: Rick Hudson <rlh@golang.org>
Diffstat (limited to 'src/runtime/mfinal.go')
-rw-r--r--src/runtime/mfinal.go5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go
index 4f3e887bc8..dae3956cd1 100644
--- a/src/runtime/mfinal.go
+++ b/src/runtime/mfinal.go
@@ -182,6 +182,11 @@ func runfinq() {
if f.fint == nil {
throw("missing type in runfinq")
}
+ // frame is effectively uninitialized
+ // memory. That means we have to clear
+ // it before writing to it to avoid
+ // confusing the write barrier.
+ *(*[2]uintptr)(frame) = [2]uintptr{}
switch f.fint.kind & kindMask {
case kindPtr:
// direct use of pointer