]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.24] weak: prevent unsafe conversions using weak pointers
authorthepudds <thepudds1460@gmail.com>
Thu, 6 Feb 2025 13:07:38 +0000 (08:07 -0500)
committerCherry Mui <cherryyz@google.com>
Thu, 6 Feb 2025 21:53:01 +0000 (13:53 -0800)
Prevent conversions between Pointer types,
like we do for sync/atomic.Pointer.

Fixes #71583

Change-Id: I20e83106d8a27996f221e6cd9d52637b0442cea4
Reviewed-on: https://go-review.googlesource.com/c/go/+/647195
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
(cherry picked from commit 8163ea1458763aa38fa9197e479bd30cb0145429)
Reviewed-on: https://go-review.googlesource.com/c/go/+/647435
Reviewed-by: Carlos Amedee <carlos@golang.org>
TryBot-Bypass: Cherry Mui <cherryyz@google.com>

src/weak/pointer.go
src/weak/pointer_test.go
test/weak.go [new file with mode: 0644]

index 39c512e76d6fe463a2e341ca925e7e8dd4e5ad3a..e9d7420880a7f92105a33a23446d08224090ef9d 100644 (file)
@@ -56,6 +56,9 @@ import (
 // referenced object. Typically, this batching only happens for tiny
 // (on the order of 16 bytes or less) and pointer-free objects.
 type Pointer[T any] struct {
+       // Mention T in the type definition to prevent conversions
+       // between Pointer types, like we do for sync/atomic.Pointer.
+       _ [0]*T
        u unsafe.Pointer
 }
 
@@ -69,7 +72,7 @@ func Make[T any](ptr *T) Pointer[T] {
                u = runtime_registerWeakPointer(unsafe.Pointer(ptr))
        }
        runtime.KeepAlive(ptr)
-       return Pointer[T]{u}
+       return Pointer[T]{u: u}
 }
 
 // Value returns the original pointer used to create the weak pointer.
index e0ef30377e9e81cc3952c9938b7a17bccec9a1eb..70c743381cacf869bd228b7ca334392bcbe9e3d5 100644 (file)
@@ -6,10 +6,12 @@ package weak_test
 
 import (
        "context"
+       "internal/goarch"
        "runtime"
        "sync"
        "testing"
        "time"
+       "unsafe"
        "weak"
 )
 
@@ -155,6 +157,14 @@ func TestPointerFinalizer(t *testing.T) {
        }
 }
 
+func TestPointerSize(t *testing.T) {
+       var p weak.Pointer[T]
+       size := unsafe.Sizeof(p)
+       if size != goarch.PtrSize {
+               t.Errorf("weak.Pointer[T] size = %d, want %d", size, goarch.PtrSize)
+       }
+}
+
 // Regression test for issue 69210.
 //
 // Weak-to-strong conversions must shade the new strong pointer, otherwise
diff --git a/test/weak.go b/test/weak.go
new file mode 100644 (file)
index 0000000..ca3ec79
--- /dev/null
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test weak pointers.
+
+package p
+
+import (
+       "runtime"
+       "weak"
+)
+
+// Adapted from example in https://github.com/golang/go/issues/67552#issuecomment-2639661220
+func conversion() {
+       p := "hello"
+       a := weak.Make(&p)
+       b := (weak.Pointer[*byte])(a) // ERROR "cannot convert a \(variable of struct type weak\.Pointer\[string\]\) to type weak.Pointer\[\*byte\]"
+       c := b.Value()
+       println(**c)
+       runtime.KeepAlive(p)
+}