diff options
| author | Katie Hockman <katie@golang.org> | 2020-12-14 10:03:05 -0500 |
|---|---|---|
| committer | Katie Hockman <katie@golang.org> | 2020-12-14 10:06:13 -0500 |
| commit | 0345ede87ee12698988973884cfc0fd3d499dffd (patch) | |
| tree | 7123cff141ee5661208d2f5f437b8f5252ac7f6a /src/reflect/value.go | |
| parent | 4651d6b267818b0e0d128a5443289717c4bb8cbc (diff) | |
| parent | 0a02371b0576964e81c3b40d328db9a3ef3b031b (diff) | |
| download | go-0345ede87ee12698988973884cfc0fd3d499dffd.tar.xz | |
[dev.fuzz] all: merge master into dev.fuzz
Change-Id: I5d8c8329ccc9d747bd81ade6b1cb7cb8ae2e94b2
Diffstat (limited to 'src/reflect/value.go')
| -rw-r--r-- | src/reflect/value.go | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go index c6f24a5609..1f185b52e4 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -90,6 +90,7 @@ func (f flag) ro() flag { // pointer returns the underlying pointer represented by v. // v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer +// if v.Kind() == Ptr, the base type must not be go:notinheap. func (v Value) pointer() unsafe.Pointer { if v.typ.size != ptrSize || !v.typ.pointers() { panic("can't call pointer on a non-pointer Value") @@ -1452,7 +1453,16 @@ func (v Value) Pointer() uintptr { // TODO: deprecate k := v.kind() switch k { - case Chan, Map, Ptr, UnsafePointer: + case Ptr: + if v.typ.ptrdata == 0 { + // Handle pointers to go:notinheap types directly, + // so we never materialize such pointers as an + // unsafe.Pointer. (Such pointers are always indirect.) + // See issue 42076. + return *(*uintptr)(v.ptr) + } + fallthrough + case Chan, Map, UnsafePointer: return uintptr(v.pointer()) case Func: if v.flag&flagMethod != 0 { @@ -1553,7 +1563,11 @@ func (v Value) Set(x Value) { } x = x.assignTo("reflect.Set", v.typ, target) if x.flag&flagIndir != 0 { - typedmemmove(v.typ, v.ptr, x.ptr) + if x.ptr == unsafe.Pointer(&zeroVal[0]) { + typedmemclr(v.typ, v.ptr) + } else { + typedmemmove(v.typ, v.ptr, x.ptr) + } } else { *(*unsafe.Pointer)(v.ptr) = x.ptr } @@ -2360,11 +2374,23 @@ func Zero(typ Type) Value { t := typ.(*rtype) fl := flag(t.Kind()) if ifaceIndir(t) { - return Value{t, unsafe_New(t), fl | flagIndir} + var p unsafe.Pointer + if t.size <= maxZero { + p = unsafe.Pointer(&zeroVal[0]) + } else { + p = unsafe_New(t) + } + return Value{t, p, fl | flagIndir} } return Value{t, nil, fl} } +// must match declarations in runtime/map.go. +const maxZero = 1024 + +//go:linkname zeroVal runtime.zeroVal +var zeroVal [maxZero]byte + // New returns a Value representing a pointer to a new zero value // for the specified type. That is, the returned Value's Type is PtrTo(typ). func New(typ Type) Value { @@ -2655,12 +2681,20 @@ func cvtComplex(v Value, t Type) Value { // convertOp: intXX -> string func cvtIntString(v Value, t Type) Value { - return makeString(v.flag.ro(), string(rune(v.Int())), t) + s := "\uFFFD" + if x := v.Int(); int64(rune(x)) == x { + s = string(rune(x)) + } + return makeString(v.flag.ro(), s, t) } // convertOp: uintXX -> string func cvtUintString(v Value, t Type) Value { - return makeString(v.flag.ro(), string(rune(v.Uint())), t) + s := "\uFFFD" + if x := v.Uint(); uint64(rune(x)) == x { + s = string(rune(x)) + } + return makeString(v.flag.ro(), s, t) } // convertOp: []byte -> string |
