mirror of
https://github.com/golang/go
synced 2024-09-24 23:20:12 -06:00
encoding/gob: consistently use unsafe.Pointer for pointer values
Fixes #5621. R=golang-dev, cshapiro, r, fullung CC=golang-dev https://golang.org/cl/9988043
This commit is contained in:
parent
2c0b00744f
commit
941db1ed39
@ -450,11 +450,11 @@ type decEngine struct {
|
||||
|
||||
// allocate makes sure storage is available for an object of underlying type rtyp
|
||||
// that is indir levels of indirection through p.
|
||||
func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
|
||||
func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer {
|
||||
if indir == 0 {
|
||||
return p
|
||||
}
|
||||
up := unsafe.Pointer(p)
|
||||
up := p
|
||||
if indir > 1 {
|
||||
up = decIndirect(up, indir)
|
||||
}
|
||||
@ -462,13 +462,13 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
|
||||
// Allocate object.
|
||||
*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
|
||||
}
|
||||
return *(*uintptr)(up)
|
||||
return *(*unsafe.Pointer)(up)
|
||||
}
|
||||
|
||||
// decodeSingle decodes a top-level value that is not a struct and stores it through p.
|
||||
// Such values are preceded by a zero, making them have the memory layout of a
|
||||
// struct field (although with an illegal field number).
|
||||
func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uintptr) {
|
||||
func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) {
|
||||
state := dec.newDecoderState(&dec.buf)
|
||||
state.fieldnum = singletonField
|
||||
delta := int(state.decodeUint())
|
||||
@ -479,7 +479,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
|
||||
if instr.indir != ut.indir {
|
||||
errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir)
|
||||
}
|
||||
ptr := unsafe.Pointer(basep) // offset will be zero
|
||||
ptr := basep // offset will be zero
|
||||
if instr.indir > 1 {
|
||||
ptr = decIndirect(ptr, instr.indir)
|
||||
}
|
||||
@ -492,7 +492,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
|
||||
// differ from ut.indir, which was computed when the engine was built.
|
||||
// This state cannot arise for decodeSingle, which is called directly
|
||||
// from the user's value, not from the innards of an engine.
|
||||
func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, indir int) {
|
||||
func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) {
|
||||
p = allocate(ut.base, p, indir)
|
||||
state := dec.newDecoderState(&dec.buf)
|
||||
state.fieldnum = -1
|
||||
@ -511,7 +511,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr,
|
||||
break
|
||||
}
|
||||
instr := &engine.instr[fieldnum]
|
||||
p := unsafe.Pointer(basep + instr.offset)
|
||||
p := unsafe.Pointer(uintptr(basep) + instr.offset)
|
||||
if instr.indir > 1 {
|
||||
p = decIndirect(p, instr.indir)
|
||||
}
|
||||
@ -559,25 +559,25 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
|
||||
}
|
||||
|
||||
// decodeArrayHelper does the work for decoding arrays and slices.
|
||||
func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
|
||||
func (dec *Decoder) decodeArrayHelper(state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
|
||||
instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
|
||||
for i := 0; i < length; i++ {
|
||||
if state.b.Len() == 0 {
|
||||
errorf("decoding array or slice: length exceeds input size (%d elements)", length)
|
||||
}
|
||||
up := unsafe.Pointer(p)
|
||||
up := p
|
||||
if elemIndir > 1 {
|
||||
up = decIndirect(up, elemIndir)
|
||||
}
|
||||
elemOp(instr, state, up)
|
||||
p += uintptr(elemWid)
|
||||
p = unsafe.Pointer(uintptr(p) + elemWid)
|
||||
}
|
||||
}
|
||||
|
||||
// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
|
||||
// The length is an unsigned integer preceding the elements. Even though the length is redundant
|
||||
// (it's part of the type), it's a useful check and is included in the encoding.
|
||||
func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
|
||||
func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
|
||||
if indir > 0 {
|
||||
p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
|
||||
}
|
||||
@ -591,7 +591,7 @@ func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintpt
|
||||
// unlike the other items we can't use a pointer directly.
|
||||
func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value {
|
||||
instr := &decInstr{op, 0, indir, 0, ovfl}
|
||||
up := unsafe.Pointer(unsafeAddr(v))
|
||||
up := unsafeAddr(v)
|
||||
if indir > 1 {
|
||||
up = decIndirect(up, indir)
|
||||
}
|
||||
@ -603,7 +603,7 @@ func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value,
|
||||
// Maps are encoded as a length followed by key:value pairs.
|
||||
// Because the internals of maps are not visible to us, we must
|
||||
// use reflection rather than pointer magic.
|
||||
func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
|
||||
func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
|
||||
if indir > 0 {
|
||||
p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
|
||||
}
|
||||
@ -673,7 +673,7 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
|
||||
hdrp.Cap = n
|
||||
}
|
||||
hdrp.Len = n
|
||||
dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
|
||||
dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl)
|
||||
}
|
||||
|
||||
// ignoreSlice skips over the data for a slice value with no destination.
|
||||
@ -693,7 +693,7 @@ func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
|
||||
// decodeInterface decodes an interface value and stores it through p.
|
||||
// Interfaces are encoded as the name of a concrete type followed by a value.
|
||||
// If the name is empty, the value is nil and no value is sent.
|
||||
func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p uintptr, indir int) {
|
||||
func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p unsafe.Pointer, indir int) {
|
||||
// Create a writable interface reflect.Value. We need one even for the nil case.
|
||||
ivalue := allocValue(ityp)
|
||||
// Read the name of the concrete type.
|
||||
@ -850,7 +850,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
|
||||
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
|
||||
ovfl := overflow(name)
|
||||
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
|
||||
state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
|
||||
state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
@ -860,8 +860,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
|
||||
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
|
||||
ovfl := overflow(name)
|
||||
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
|
||||
up := unsafe.Pointer(p)
|
||||
state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
|
||||
state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
|
||||
}
|
||||
|
||||
case reflect.Slice:
|
||||
@ -890,11 +889,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
|
||||
}
|
||||
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
|
||||
// indirect through enginePtr to delay evaluation for recursive structs.
|
||||
dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir)
|
||||
dec.decodeStruct(*enginePtr, userType(typ), p, i.indir)
|
||||
}
|
||||
case reflect.Interface:
|
||||
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
|
||||
state.dec.decodeInterface(t, state, uintptr(p), i.indir)
|
||||
state.dec.decodeInterface(t, state, p, i.indir)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1229,9 +1228,9 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
|
||||
name := base.Name()
|
||||
errorf("type mismatch: no fields matched compiling decoder for %s", name)
|
||||
}
|
||||
dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir)
|
||||
dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir)
|
||||
} else {
|
||||
dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val)))
|
||||
dec.decodeSingle(engine, ut, unsafeAddr(val))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1283,13 +1282,13 @@ func init() {
|
||||
// into existing structs or slices cannot be addressed,
|
||||
// so simulate it by returning a pointer to a copy.
|
||||
// Each call allocates once.
|
||||
func unsafeAddr(v reflect.Value) uintptr {
|
||||
func unsafeAddr(v reflect.Value) unsafe.Pointer {
|
||||
if v.CanAddr() {
|
||||
return v.UnsafeAddr()
|
||||
return unsafe.Pointer(v.UnsafeAddr())
|
||||
}
|
||||
x := reflect.New(v.Type()).Elem()
|
||||
x.Set(v)
|
||||
return x.UnsafeAddr()
|
||||
return unsafe.Pointer(x.UnsafeAddr())
|
||||
}
|
||||
|
||||
// Gob depends on being able to take the address
|
||||
|
@ -338,14 +338,14 @@ type encEngine struct {
|
||||
const singletonField = 0
|
||||
|
||||
// encodeSingle encodes a single top-level non-struct value.
|
||||
func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) {
|
||||
func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
|
||||
state := enc.newEncoderState(b)
|
||||
state.fieldnum = singletonField
|
||||
// There is no surrounding struct to frame the transmission, so we must
|
||||
// generate data even if the item is zero. To do this, set sendZero.
|
||||
state.sendZero = true
|
||||
instr := &engine.instr[singletonField]
|
||||
p := unsafe.Pointer(basep) // offset will be zero
|
||||
p := basep // offset will be zero
|
||||
if instr.indir > 0 {
|
||||
if p = encIndirect(p, instr.indir); p == nil {
|
||||
return
|
||||
@ -356,12 +356,12 @@ func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintp
|
||||
}
|
||||
|
||||
// encodeStruct encodes a single struct value.
|
||||
func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) {
|
||||
func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
|
||||
state := enc.newEncoderState(b)
|
||||
state.fieldnum = -1
|
||||
for i := 0; i < len(engine.instr); i++ {
|
||||
instr := &engine.instr[i]
|
||||
p := unsafe.Pointer(basep + instr.offset)
|
||||
p := unsafe.Pointer(uintptr(basep) + instr.offset)
|
||||
if instr.indir > 0 {
|
||||
if p = encIndirect(p, instr.indir); p == nil {
|
||||
continue
|
||||
@ -373,22 +373,22 @@ func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintp
|
||||
}
|
||||
|
||||
// encodeArray encodes the array whose 0th element is at p.
|
||||
func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) {
|
||||
func (enc *Encoder) encodeArray(b *bytes.Buffer, p unsafe.Pointer, op encOp, elemWid uintptr, elemIndir int, length int) {
|
||||
state := enc.newEncoderState(b)
|
||||
state.fieldnum = -1
|
||||
state.sendZero = true
|
||||
state.encodeUint(uint64(length))
|
||||
for i := 0; i < length; i++ {
|
||||
elemp := p
|
||||
up := unsafe.Pointer(elemp)
|
||||
if elemIndir > 0 {
|
||||
if up = encIndirect(up, elemIndir); up == nil {
|
||||
up := encIndirect(elemp, elemIndir)
|
||||
if up == nil {
|
||||
errorf("encodeArray: nil element")
|
||||
}
|
||||
elemp = uintptr(up)
|
||||
elemp = up
|
||||
}
|
||||
op(nil, state, unsafe.Pointer(elemp))
|
||||
p += uintptr(elemWid)
|
||||
op(nil, state, elemp)
|
||||
p = unsafe.Pointer(uintptr(p) + elemWid)
|
||||
}
|
||||
enc.freeEncoderState(state)
|
||||
}
|
||||
@ -401,7 +401,7 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in
|
||||
if !v.IsValid() {
|
||||
errorf("encodeReflectValue: nil element")
|
||||
}
|
||||
op(nil, state, unsafe.Pointer(unsafeAddr(v)))
|
||||
op(nil, state, unsafeAddr(v))
|
||||
}
|
||||
|
||||
// encodeMap encodes a map as unsigned count followed by key:value pairs.
|
||||
@ -582,14 +582,14 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
|
||||
return
|
||||
}
|
||||
state.update(i)
|
||||
state.enc.encodeArray(state.b, slice.Data, *elemOp, t.Elem().Size(), indir, int(slice.Len))
|
||||
state.enc.encodeArray(state.b, unsafe.Pointer(slice.Data), *elemOp, t.Elem().Size(), indir, int(slice.Len))
|
||||
}
|
||||
case reflect.Array:
|
||||
// True arrays have size in the type.
|
||||
elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
|
||||
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
|
||||
state.update(i)
|
||||
state.enc.encodeArray(state.b, uintptr(p), *elemOp, t.Elem().Size(), indir, t.Len())
|
||||
state.enc.encodeArray(state.b, p, *elemOp, t.Elem().Size(), indir, t.Len())
|
||||
}
|
||||
case reflect.Map:
|
||||
keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress)
|
||||
@ -615,7 +615,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
|
||||
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
|
||||
state.update(i)
|
||||
// indirect through info to delay evaluation for recursive structs
|
||||
state.enc.encodeStruct(state.b, info.encoder, uintptr(p))
|
||||
state.enc.encodeStruct(state.b, info.encoder, p)
|
||||
}
|
||||
case reflect.Interface:
|
||||
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
|
||||
|
Loading…
Reference in New Issue
Block a user