From 941db1ed39cfb5a80ceb94dc24766165a1d1bd68 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 4 Jun 2013 06:20:57 -0700 Subject: [PATCH] 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 --- src/pkg/encoding/gob/decode.go | 49 +++++++++++++++++----------------- src/pkg/encoding/gob/encode.go | 28 +++++++++---------- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/pkg/encoding/gob/decode.go b/src/pkg/encoding/gob/decode.go index 7cc7565409c..08829a4a0a0 100644 --- a/src/pkg/encoding/gob/decode.go +++ b/src/pkg/encoding/gob/decode.go @@ -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 diff --git a/src/pkg/encoding/gob/encode.go b/src/pkg/encoding/gob/encode.go index ea37a6cbd58..6fcf8f9a5d8 100644 --- a/src/pkg/encoding/gob/encode.go +++ b/src/pkg/encoding/gob/encode.go @@ -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) {