]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: handle String kind in Value.{Pointer,UnsafePointer}
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Tue, 8 Aug 2023 02:51:22 +0000 (09:51 +0700)
committerGopher Robot <gobot@golang.org>
Tue, 2 Apr 2024 21:51:14 +0000 (21:51 +0000)
Updates #61308

Change-Id: I92d459383c520d137787ce5c8f135d205af74e5d
Reviewed-on: https://go-review.googlesource.com/c/go/+/516596
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/reflect/all_test.go
src/reflect/value.go

index 6e5c7d12e2c9741d5f4dccc692a5a31f4de9673e..daeabae933eb9a585bcfbf99a06f7bbbedd49b26 100644 (file)
@@ -8512,3 +8512,39 @@ func TestClear(t *testing.T) {
                })
        }
 }
+
+func TestValuePointerAndUnsafePointer(t *testing.T) {
+       ptr := new(int)
+       ch := make(chan int)
+       m := make(map[int]int)
+       unsafePtr := unsafe.Pointer(ptr)
+       slice := make([]int, 1)
+       fn := func() {}
+       s := "foo"
+
+       tests := []struct {
+               name              string
+               val               Value
+               wantUnsafePointer unsafe.Pointer
+       }{
+               {"pointer", ValueOf(ptr), unsafe.Pointer(ptr)},
+               {"channel", ValueOf(ch), *(*unsafe.Pointer)(unsafe.Pointer(&ch))},
+               {"map", ValueOf(m), *(*unsafe.Pointer)(unsafe.Pointer(&m))},
+               {"unsafe.Pointer", ValueOf(unsafePtr), unsafePtr},
+               {"function", ValueOf(fn), **(**unsafe.Pointer)(unsafe.Pointer(&fn))},
+               {"slice", ValueOf(slice), unsafe.Pointer(unsafe.SliceData(slice))},
+               {"string", ValueOf(s), unsafe.Pointer(unsafe.StringData(s))},
+       }
+
+       for _, tc := range tests {
+               tc := tc
+               t.Run(tc.name, func(t *testing.T) {
+                       if got := tc.val.Pointer(); got != uintptr(tc.wantUnsafePointer) {
+                               t.Errorf("unexpected uintptr result, got %#x, want %#x", got, uintptr(tc.wantUnsafePointer))
+                       }
+                       if got := tc.val.UnsafePointer(); got != tc.wantUnsafePointer {
+                               t.Errorf("unexpected unsafe.Pointer result, got %#x, want %#x", got, tc.wantUnsafePointer)
+                       }
+               })
+       }
+}
index 9cde9d0975436214100e4638f07a32e6d5dca25c..dd7021b104f241b5ec1264079152c5c0b72ffe0f 100644 (file)
@@ -2184,7 +2184,7 @@ func (v Value) OverflowUint(x uint64) bool {
 // and make an exception.
 
 // Pointer returns v's value as a uintptr.
-// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], or [UnsafePointer].
+// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], [String], or [UnsafePointer].
 //
 // If v's Kind is [Func], the returned pointer is an underlying
 // code pointer, but not necessarily enough to identify a
@@ -2195,6 +2195,9 @@ func (v Value) OverflowUint(x uint64) bool {
 // element of the slice. If the slice is nil the returned value
 // is 0.  If the slice is empty but non-nil the return value is non-zero.
 //
+// If v's Kind is [String], the returned pointer is to the first
+// element of the underlying bytes of string.
+//
 // It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result.
 func (v Value) Pointer() uintptr {
        // The compiler loses track as it converts to uintptr. Force escape.
@@ -2232,9 +2235,10 @@ func (v Value) Pointer() uintptr {
                        p = *(*unsafe.Pointer)(p)
                }
                return uintptr(p)
-
        case Slice:
                return uintptr((*unsafeheader.Slice)(v.ptr).Data)
+       case String:
+               return uintptr((*unsafeheader.String)(v.ptr).Data)
        }
        panic(&ValueError{"reflect.Value.Pointer", v.kind()})
 }
@@ -2779,6 +2783,9 @@ func (v Value) UnsafeAddr() uintptr {
 // If v's Kind is [Slice], the returned pointer is to the first
 // element of the slice. If the slice is nil the returned value
 // is nil.  If the slice is empty but non-nil the return value is non-nil.
+//
+// If v's Kind is [String], the returned pointer is to the first
+// element of the underlying bytes of string.
 func (v Value) UnsafePointer() unsafe.Pointer {
        k := v.kind()
        switch k {
@@ -2812,9 +2819,10 @@ func (v Value) UnsafePointer() unsafe.Pointer {
                        p = *(*unsafe.Pointer)(p)
                }
                return p
-
        case Slice:
                return (*unsafeheader.Slice)(v.ptr).Data
+       case String:
+               return (*unsafeheader.String)(v.ptr).Data
        }
        panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()})
 }