Skip to content

Commit b7b4c60

Browse files
thepuddscherrymui
authored andcommitted
[release-branch.go1.24] weak: prevent unsafe conversions using weak pointers
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 <[email protected]> Auto-Submit: Michael Knyszek <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> Reviewed-by: Cherry Mui <[email protected]> (cherry picked from commit 8163ea1) Reviewed-on: https://go-review.googlesource.com/c/go/+/647435 Reviewed-by: Carlos Amedee <[email protected]> TryBot-Bypass: Cherry Mui <[email protected]>
1 parent 18068cb commit b7b4c60

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

src/weak/pointer.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ import (
5656
// referenced object. Typically, this batching only happens for tiny
5757
// (on the order of 16 bytes or less) and pointer-free objects.
5858
type Pointer[T any] struct {
59+
// Mention T in the type definition to prevent conversions
60+
// between Pointer types, like we do for sync/atomic.Pointer.
61+
_ [0]*T
5962
u unsafe.Pointer
6063
}
6164

@@ -69,7 +72,7 @@ func Make[T any](ptr *T) Pointer[T] {
6972
u = runtime_registerWeakPointer(unsafe.Pointer(ptr))
7073
}
7174
runtime.KeepAlive(ptr)
72-
return Pointer[T]{u}
75+
return Pointer[T]{u: u}
7376
}
7477

7578
// Value returns the original pointer used to create the weak pointer.

src/weak/pointer_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ package weak_test
66

77
import (
88
"context"
9+
"internal/goarch"
910
"runtime"
1011
"sync"
1112
"testing"
1213
"time"
14+
"unsafe"
1315
"weak"
1416
)
1517

@@ -155,6 +157,14 @@ func TestPointerFinalizer(t *testing.T) {
155157
}
156158
}
157159

160+
func TestPointerSize(t *testing.T) {
161+
var p weak.Pointer[T]
162+
size := unsafe.Sizeof(p)
163+
if size != goarch.PtrSize {
164+
t.Errorf("weak.Pointer[T] size = %d, want %d", size, goarch.PtrSize)
165+
}
166+
}
167+
158168
// Regression test for issue 69210.
159169
//
160170
// Weak-to-strong conversions must shade the new strong pointer, otherwise

test/weak.go

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// errorcheck
2+
3+
// Copyright 2025 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Test weak pointers.
8+
9+
package p
10+
11+
import (
12+
"runtime"
13+
"weak"
14+
)
15+
16+
// Adapted from example in https://github.com/golang/go/issues/67552#issuecomment-2639661220
17+
func conversion() {
18+
p := "hello"
19+
a := weak.Make(&p)
20+
b := (weak.Pointer[*byte])(a) // ERROR "cannot convert a \(variable of struct type weak\.Pointer\[string\]\) to type weak.Pointer\[\*byte\]"
21+
c := b.Value()
22+
println(**c)
23+
runtime.KeepAlive(p)
24+
}

0 commit comments

Comments
 (0)