]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: make unsafe.Slice usable from nowritebarrierrec
authorAustin Clements <austin@google.com>
Mon, 13 Feb 2023 20:55:21 +0000 (15:55 -0500)
committerAustin Clements <austin@google.com>
Fri, 10 Mar 2023 17:59:31 +0000 (17:59 +0000)
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>
src/runtime/unsafe.go

index 54649e8ff5da728d900543faebd21fcd8f5db1c9..d2773bc56d0f50a8f845aba354ffe48a1c76498c 100644 (file)
@@ -52,21 +52,21 @@ func panicunsafestringnilptr() {
 // Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
 func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
        if len < 0 {
-               panicunsafeslicelen()
+               panicunsafeslicelen1(getcallerpc())
        }
 
        if et.size == 0 {
                if ptr == nil && len > 0 {
-                       panicunsafeslicenilptr()
+                       panicunsafeslicenilptr1(getcallerpc())
                }
        }
 
        mem, overflow := math.MulUintptr(et.size, uintptr(len))
        if overflow || mem > -uintptr(ptr) {
                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) {
        len := int(len64)
        if int64(len) != len64 {
-               panicunsafeslicelen()
+               panicunsafeslicelen1(getcallerpc())
        }
        unsafeslice(et, ptr, len)
 }
@@ -90,9 +90,25 @@ func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
 }
 
 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"))
 }
 
 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"))
 }