1
0
mirror of https://github.com/golang/go synced 2024-11-17 17:04:47 -07:00

runtime: make unsafe.Slice usable from nowritebarrierrec

Many compiler-generated panics are dynamically changed to a "throw"
when they happen in the runtime. One effect of this is that they are
allowed in nowritebarrierrec contexts. Currently, the unsafe.Slice
panics don't have this treatment.

We're about to expose more code that uses unsafe.Slice to the write
barrier checker (it's actually already there and it just can't see
through an indirect call), so give these panics the dynamic check.

Very indirectly updates #54466.

Change-Id: I65cb96fa17eb751041e4fa25a1c1bd03246c82ba
Reviewed-on: https://go-review.googlesource.com/c/go/+/468296
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Austin Clements 2023-02-13 15:55:21 -05:00
parent f758d648b0
commit da384766a0

View File

@ -52,21 +52,21 @@ func panicunsafestringnilptr() {
// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice // Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
func unsafeslice(et *_type, ptr unsafe.Pointer, len int) { func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
if len < 0 { if len < 0 {
panicunsafeslicelen() panicunsafeslicelen1(getcallerpc())
} }
if et.size == 0 { if et.size == 0 {
if ptr == nil && len > 0 { if ptr == nil && len > 0 {
panicunsafeslicenilptr() panicunsafeslicenilptr1(getcallerpc())
} }
} }
mem, overflow := math.MulUintptr(et.size, uintptr(len)) mem, overflow := math.MulUintptr(et.size, uintptr(len))
if overflow || mem > -uintptr(ptr) { if overflow || mem > -uintptr(ptr) {
if ptr == nil { if ptr == nil {
panicunsafeslicenilptr() panicunsafeslicenilptr1(getcallerpc())
} }
panicunsafeslicelen() panicunsafeslicelen1(getcallerpc())
} }
} }
@ -74,7 +74,7 @@ func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) { func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
len := int(len64) len := int(len64)
if int64(len) != len64 { if int64(len) != len64 {
panicunsafeslicelen() panicunsafeslicelen1(getcallerpc())
} }
unsafeslice(et, ptr, len) unsafeslice(et, ptr, len)
} }
@ -90,9 +90,25 @@ func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
} }
func panicunsafeslicelen() { func panicunsafeslicelen() {
// This is called only from compiler-generated code, so we can get the
// source of the panic.
panicunsafeslicelen1(getcallerpc())
}
//go:yeswritebarrierrec
func panicunsafeslicelen1(pc uintptr) {
panicCheck1(pc, "unsafe.Slice: len out of range")
panic(errorString("unsafe.Slice: len out of range")) panic(errorString("unsafe.Slice: len out of range"))
} }
func panicunsafeslicenilptr() { func panicunsafeslicenilptr() {
// This is called only from compiler-generated code, so we can get the
// source of the panic.
panicunsafeslicenilptr1(getcallerpc())
}
//go:yeswritebarrierrec
func panicunsafeslicenilptr1(pc uintptr) {
panicCheck1(pc, "unsafe.Slice: ptr is nil and len is not zero")
panic(errorString("unsafe.Slice: ptr is nil and len is not zero")) panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
} }