Skip to content

Commit

Permalink
runtime: clear mspan.largeType more carefully in the case of arenas
Browse files Browse the repository at this point in the history
The pointer stored in mspan.largeType is an invalid pointer when
the span is an arena. We need to make sure that pointer isn't seen
by the garbage collector, as it might barf on it. Make sure we
zero the pointer using a uintptr write so the old value isn't picked
up by the write barrier.

The mspan.largeType field itself is in a NotInHeap struct, so a heap
scan won't find it. The only way we find it is when writing it, or
when reading it and putting it in a GC-reachable location. I think we
might need to audit the runtime to make sure these pointers aren't
being passed in places where the GC might (non-conservatively) scan a
stack frame it lives in. (It might be ok, many such places are either
systemstack or nosplit.)

Change-Id: Ie059d054e0da4d48a4c4b3be88b8e1e46ffa7d10
Reviewed-on: https://go-review.googlesource.com/c/go/+/548535
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
randall77 committed Dec 11, 2023
1 parent 59275e2 commit 052d402
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/runtime/mgcsweep.go
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,10 @@ func (sl *sweepLocked) sweep(preserve bool) bool {
s := spanOf(uintptr(unsafe.Pointer(s.largeType)))
mheap_.freeManual(s, spanAllocPtrScalarBits)
})
s.largeType = nil
// Make sure to zero this pointer without putting the old
// value in a write buffer, as the old value might be an
// invalid pointer. See arena.go:(*mheap).allocUserArenaChunk.
*(*uintptr)(unsafe.Pointer(&s.largeType)) = 0
}

// Count the free in the consistent, external stats.
Expand Down

0 comments on commit 052d402

Please sign in to comment.