src/reflect: make sure indirect pointers are handled correctly

Fixes #2370
Fixes #2323
Этот коммит содержится в:
Damian Gryski 2021-12-15 13:08:36 -08:00 коммит произвёл Ron Evans
родитель 38b14706e2
коммит 518745ea79

Просмотреть файл

@ -108,10 +108,7 @@ func (v Value) Kind() Kind {
func (v Value) IsNil() bool { func (v Value) IsNil() bool {
switch v.Kind() { switch v.Kind() {
case Chan, Map, Ptr: case Chan, Map, Ptr:
if v.isIndirect() { return v.pointer() == nil
return *(*uintptr)(v.value) == 0
}
return v.value == nil
case Func: case Func:
if v.value == nil { if v.value == nil {
return true return true
@ -355,9 +352,9 @@ func (v Value) Len() int {
case Array: case Array:
return v.typecode.Len() return v.typecode.Len()
case Chan: case Chan:
return chanlen(v.value) return chanlen(v.pointer())
case Map: case Map:
return maplen(v.value) return maplen(v.pointer())
case Slice: case Slice:
return int((*sliceHeader)(v.value).len) return int((*sliceHeader)(v.value).len)
case String: case String:
@ -377,7 +374,7 @@ func (v Value) Cap() int {
case Array: case Array:
return v.typecode.Len() return v.typecode.Len()
case Chan: case Chan:
return chancap(v.value) return chancap(v.pointer())
case Slice: case Slice:
return int((*sliceHeader)(v.value).cap) return int((*sliceHeader)(v.value).cap)
default: default:
@ -394,10 +391,7 @@ func (v Value) NumField() int {
func (v Value) Elem() Value { func (v Value) Elem() Value {
switch v.Kind() { switch v.Kind() {
case Ptr: case Ptr:
ptr := v.value ptr := v.pointer()
if v.isIndirect() {
ptr = *(*unsafe.Pointer)(ptr)
}
if ptr == nil { if ptr == nil {
return Value{} return Value{}
} }
@ -531,8 +525,8 @@ func (v Value) Index(i int) Value {
} }
} }
if size > unsafe.Sizeof(uintptr(0)) { if size > unsafe.Sizeof(uintptr(0)) || v.isIndirect() {
// The element fits in a pointer, but the array does not. // The element fits in a pointer, but the array is not stored in the pointer directly.
// Load the value from the pointer. // Load the value from the pointer.
addr := unsafe.Pointer(uintptr(v.value) + elemSize*uintptr(i)) // pointer to new value addr := unsafe.Pointer(uintptr(v.value) + elemSize*uintptr(i)) // pointer to new value
value := addr value := addr