mirror of
https://github.com/golang/go
synced 2024-11-21 19:24:45 -07:00
changes for more restricted reflect.SetValue
R=golang-dev, r CC=golang-dev https://golang.org/cl/4423043
This commit is contained in:
parent
40fccbce6b
commit
cded21a337
@ -276,21 +276,21 @@ func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value)
|
||||
return v
|
||||
|
||||
case reflect.Struct:
|
||||
v := reflect.Zero(p.Type())
|
||||
v := reflect.New(p.Type()).Elem()
|
||||
for i := 0; i < p.NumField(); i++ {
|
||||
v.Field(i).Set(subst(m, p.Field(i), pos))
|
||||
}
|
||||
return v
|
||||
|
||||
case reflect.Ptr:
|
||||
v := reflect.Zero(p.Type())
|
||||
v := reflect.New(p.Type()).Elem()
|
||||
if elem := p.Elem(); elem.IsValid() {
|
||||
v.Set(subst(m, elem, pos).Addr())
|
||||
}
|
||||
return v
|
||||
|
||||
case reflect.Interface:
|
||||
v := reflect.Zero(p.Type())
|
||||
v := reflect.New(p.Type()).Elem()
|
||||
if elem := p.Elem(); elem.IsValid() {
|
||||
v.Set(subst(m, elem, pos))
|
||||
}
|
||||
|
@ -267,11 +267,6 @@ func TestParseFieldParameters(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type unmarshalTest struct {
|
||||
in []byte
|
||||
out interface{}
|
||||
}
|
||||
|
||||
type TestObjectIdentifierStruct struct {
|
||||
OID ObjectIdentifier
|
||||
}
|
||||
@ -290,7 +285,10 @@ type TestElementsAfterString struct {
|
||||
A, B int
|
||||
}
|
||||
|
||||
var unmarshalTestData []unmarshalTest = []unmarshalTest{
|
||||
var unmarshalTestData = []struct {
|
||||
in []byte
|
||||
out interface{}
|
||||
}{
|
||||
{[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
|
||||
{[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
|
||||
{[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
|
||||
@ -309,9 +307,7 @@ var unmarshalTestData []unmarshalTest = []unmarshalTest{
|
||||
|
||||
func TestUnmarshal(t *testing.T) {
|
||||
for i, test := range unmarshalTestData {
|
||||
pv := reflect.Zero(reflect.NewValue(test.out).Type())
|
||||
zv := reflect.Zero(pv.Type().Elem())
|
||||
pv.Set(zv.Addr())
|
||||
pv := reflect.New(reflect.Typeof(test.out).Elem())
|
||||
val := pv.Interface()
|
||||
_, err := Unmarshal(test.in, val)
|
||||
if err != nil {
|
||||
|
@ -999,7 +999,6 @@ type Bad0 struct {
|
||||
C float64
|
||||
}
|
||||
|
||||
|
||||
func TestInvalidField(t *testing.T) {
|
||||
var bad0 Bad0
|
||||
bad0.CH = make(chan int)
|
||||
|
@ -581,7 +581,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 os.ErrorString) reflect.Value {
|
||||
instr := &decInstr{op, 0, indir, 0, ovfl}
|
||||
up := unsafe.Pointer(v.UnsafeAddr())
|
||||
up := unsafe.Pointer(unsafeAddr(v))
|
||||
if indir > 1 {
|
||||
up = decIndirect(up, indir)
|
||||
}
|
||||
@ -608,8 +608,8 @@ func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr,
|
||||
v := reflect.NewValue(unsafe.Unreflect(mtyp, unsafe.Pointer(p)))
|
||||
n := int(state.decodeUint())
|
||||
for i := 0; i < n; i++ {
|
||||
key := decodeIntoValue(state, keyOp, keyIndir, reflect.Zero(mtyp.Key()), ovfl)
|
||||
elem := decodeIntoValue(state, elemOp, elemIndir, reflect.Zero(mtyp.Elem()), ovfl)
|
||||
key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
|
||||
elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl)
|
||||
v.SetMapIndex(key, elem)
|
||||
}
|
||||
}
|
||||
@ -686,8 +686,8 @@ func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
|
||||
// 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) {
|
||||
// Create an interface reflect.Value. We need one even for the nil case.
|
||||
ivalue := reflect.Zero(ityp)
|
||||
// Create a writable interface reflect.Value. We need one even for the nil case.
|
||||
ivalue := allocValue(ityp)
|
||||
// Read the name of the concrete type.
|
||||
b := make([]byte, state.decodeUint())
|
||||
state.b.Read(b)
|
||||
@ -712,7 +712,7 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui
|
||||
// in case we want to ignore the value by skipping it completely).
|
||||
state.decodeUint()
|
||||
// Read the concrete value.
|
||||
value := reflect.Zero(typ)
|
||||
value := allocValue(typ)
|
||||
dec.decodeValue(concreteId, value)
|
||||
if dec.err != nil {
|
||||
error(dec.err)
|
||||
@ -1209,9 +1209,9 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
|
||||
name := base.Name()
|
||||
errorf("gob: type mismatch: no fields matched compiling decoder for %s", name)
|
||||
}
|
||||
dec.decodeStruct(engine, ut, uintptr(val.UnsafeAddr()), ut.indir)
|
||||
dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir)
|
||||
} else {
|
||||
dec.decodeSingle(engine, ut, uintptr(val.UnsafeAddr()))
|
||||
dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1256,3 +1256,26 @@ func init() {
|
||||
}
|
||||
decOpTable[reflect.Uintptr] = uop
|
||||
}
|
||||
|
||||
// Gob assumes it can call UnsafeAddr on any Value
|
||||
// in order to get a pointer it can copy data from.
|
||||
// Values that have just been created and do not point
|
||||
// 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 {
|
||||
if v.CanAddr() {
|
||||
return v.UnsafeAddr()
|
||||
}
|
||||
x := reflect.New(v.Type()).Elem()
|
||||
x.Set(v)
|
||||
return x.UnsafeAddr()
|
||||
}
|
||||
|
||||
// Gob depends on being able to take the address
|
||||
// of zeroed Values it creates, so use this wrapper instead
|
||||
// of the standard reflect.Zero.
|
||||
// Each call allocates once.
|
||||
func allocValue(t reflect.Type) reflect.Value {
|
||||
return reflect.New(t).Elem()
|
||||
}
|
||||
|
@ -171,12 +171,18 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
|
||||
return dec.DecodeValue(value)
|
||||
}
|
||||
|
||||
// DecodeValue reads the next value from the connection and stores
|
||||
// it in the data represented by the reflection value.
|
||||
// The value must be the correct type for the next
|
||||
// data item received, or it may be nil, which means the
|
||||
// value will be discarded.
|
||||
func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
|
||||
// DecodeValue reads the next value from the connection.
|
||||
// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
|
||||
// Otherwise, it stores the value into v. In that case, v must represent
|
||||
// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
|
||||
func (dec *Decoder) DecodeValue(v reflect.Value) os.Error {
|
||||
if v.IsValid() {
|
||||
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||
// That's okay, we'll store through the pointer.
|
||||
} else if !v.CanSet() {
|
||||
return os.ErrorString("gob: DecodeValue of unassignable value")
|
||||
}
|
||||
}
|
||||
// Make sure we're single-threaded through here.
|
||||
dec.mutex.Lock()
|
||||
defer dec.mutex.Unlock()
|
||||
@ -185,7 +191,7 @@ func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
|
||||
dec.err = nil
|
||||
id := dec.decodeTypeSequence(false)
|
||||
if dec.err == nil {
|
||||
dec.decodeValue(id, value)
|
||||
dec.decodeValue(id, v)
|
||||
}
|
||||
return dec.err
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in
|
||||
if !v.IsValid() {
|
||||
errorf("gob: encodeReflectValue: nil element")
|
||||
}
|
||||
op(nil, state, unsafe.Pointer(v.UnsafeAddr()))
|
||||
op(nil, state, unsafe.Pointer(unsafeAddr(v)))
|
||||
}
|
||||
|
||||
// encodeMap encodes a map as unsigned count followed by key:value pairs.
|
||||
@ -695,8 +695,8 @@ func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInf
|
||||
value = reflect.Indirect(value)
|
||||
}
|
||||
if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct {
|
||||
enc.encodeStruct(b, engine, value.UnsafeAddr())
|
||||
enc.encodeStruct(b, engine, unsafeAddr(value))
|
||||
} else {
|
||||
enc.encodeSingle(b, engine, value.UnsafeAddr())
|
||||
enc.encodeSingle(b, engine, unsafeAddr(value))
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ func TestTypeToPtrType(t *testing.T) {
|
||||
A int
|
||||
}
|
||||
t0 := Type0{7}
|
||||
t0p := (*Type0)(nil)
|
||||
t0p := new(Type0)
|
||||
if err := encAndDec(t0, t0p); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
@ -124,8 +124,7 @@ func (d *decodeState) unmarshal(v interface{}) (err os.Error) {
|
||||
|
||||
rv := reflect.NewValue(v)
|
||||
pv := rv
|
||||
if pv.Kind() != reflect.Ptr ||
|
||||
pv.IsNil() {
|
||||
if pv.Kind() != reflect.Ptr || pv.IsNil() {
|
||||
return &InvalidUnmarshalError{reflect.Typeof(v)}
|
||||
}
|
||||
|
||||
@ -267,17 +266,17 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
|
||||
v = iv.Elem()
|
||||
continue
|
||||
}
|
||||
|
||||
pv := v
|
||||
if pv.Kind() != reflect.Ptr {
|
||||
break
|
||||
}
|
||||
|
||||
if pv.Elem().Kind() != reflect.Ptr &&
|
||||
wantptr && !isUnmarshaler {
|
||||
if pv.Elem().Kind() != reflect.Ptr && wantptr && pv.CanSet() && !isUnmarshaler {
|
||||
return nil, pv
|
||||
}
|
||||
if pv.IsNil() {
|
||||
pv.Set(reflect.Zero(pv.Type().Elem()).Addr())
|
||||
pv.Set(reflect.New(pv.Type().Elem()))
|
||||
}
|
||||
if isUnmarshaler {
|
||||
// Using v.Interface().(Unmarshaler)
|
||||
@ -443,6 +442,8 @@ func (d *decodeState) object(v reflect.Value) {
|
||||
return
|
||||
}
|
||||
|
||||
var mapElem reflect.Value
|
||||
|
||||
for {
|
||||
// Read opening " of string key or closing }.
|
||||
op := d.scanWhile(scanSkipSpace)
|
||||
@ -466,7 +467,13 @@ func (d *decodeState) object(v reflect.Value) {
|
||||
// Figure out field corresponding to key.
|
||||
var subv reflect.Value
|
||||
if mv.IsValid() {
|
||||
subv = reflect.Zero(mv.Type().Elem())
|
||||
elemType := mv.Type().Elem()
|
||||
if !mapElem.IsValid() {
|
||||
mapElem = reflect.New(elemType).Elem()
|
||||
} else {
|
||||
mapElem.Set(reflect.Zero(elemType))
|
||||
}
|
||||
subv = mapElem
|
||||
} else {
|
||||
var f reflect.StructField
|
||||
var ok bool
|
||||
|
@ -138,8 +138,7 @@ func TestUnmarshal(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
// v = new(right-type)
|
||||
v := reflect.NewValue(tt.ptr)
|
||||
v.Set(reflect.Zero(v.Type().Elem()).Addr())
|
||||
v := reflect.New(reflect.Typeof(tt.ptr).Elem())
|
||||
if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
|
||||
t.Errorf("#%d: %v want %v", i, err, tt.err)
|
||||
continue
|
||||
|
@ -221,7 +221,7 @@ func (client *expClient) serveSend(hdr header) {
|
||||
return
|
||||
}
|
||||
// Create a new value for each received item.
|
||||
val := reflect.Zero(nch.ch.Type().Elem())
|
||||
val := reflect.New(nch.ch.Type().Elem()).Elem()
|
||||
if err := client.decode(val); err != nil {
|
||||
expLog("value decode:", err, "; type ", nch.ch.Type())
|
||||
return
|
||||
|
@ -133,7 +133,7 @@ func (imp *Importer) run() {
|
||||
ackHdr.SeqNum = hdr.SeqNum
|
||||
imp.encode(ackHdr, payAck, nil)
|
||||
// Create a new value for each received item.
|
||||
value := reflect.Zero(nch.ch.Type().Elem())
|
||||
value := reflect.New(nch.ch.Type().Elem()).Elem()
|
||||
if e := imp.decode(value); e != nil {
|
||||
impLog("importer value decode:", e)
|
||||
return
|
||||
|
@ -297,12 +297,6 @@ type InvalidRequest struct{}
|
||||
|
||||
var invalidRequest = InvalidRequest{}
|
||||
|
||||
func _new(t reflect.Type) reflect.Value {
|
||||
v := reflect.Zero(t)
|
||||
v.Set(reflect.Zero(t.Elem()).Addr())
|
||||
return v
|
||||
}
|
||||
|
||||
func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
|
||||
resp := server.getResponse()
|
||||
// Encode the response header
|
||||
@ -411,8 +405,8 @@ func (server *Server) ServeCodec(codec ServerCodec) {
|
||||
}
|
||||
|
||||
// Decode the argument value.
|
||||
argv := _new(mtype.ArgType)
|
||||
replyv := _new(mtype.ReplyType)
|
||||
argv := reflect.New(mtype.ArgType.Elem())
|
||||
replyv := reflect.New(mtype.ReplyType.Elem())
|
||||
err = codec.ReadRequestBody(argv.Interface())
|
||||
if err != nil {
|
||||
if err == os.EOF || err == io.ErrUnexpectedEOF {
|
||||
|
@ -107,8 +107,8 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
|
||||
if !ok {
|
||||
return reflect.Value{}, false
|
||||
}
|
||||
p := reflect.Zero(concrete)
|
||||
p.Set(v.Addr())
|
||||
p := reflect.New(concrete.Elem())
|
||||
p.Elem().Set(v)
|
||||
return p, true
|
||||
case reflect.Slice:
|
||||
numElems := rand.Intn(complexSize)
|
||||
@ -129,7 +129,7 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
|
||||
}
|
||||
return reflect.NewValue(string(codePoints)), true
|
||||
case reflect.Struct:
|
||||
s := reflect.Zero(t)
|
||||
s := reflect.New(t).Elem()
|
||||
for i := 0; i < s.NumField(); i++ {
|
||||
v, ok := Value(concrete.Field(i).Type, rand)
|
||||
if !ok {
|
||||
|
@ -288,9 +288,7 @@ var pathTests = []interface{}{
|
||||
|
||||
func TestUnmarshalPaths(t *testing.T) {
|
||||
for _, pt := range pathTests {
|
||||
p := reflect.Zero(reflect.NewValue(pt).Type())
|
||||
p.Set(reflect.Zero(p.Type().Elem()).Addr())
|
||||
v := p.Interface()
|
||||
v := reflect.New(reflect.Typeof(pt).Elem()).Interface()
|
||||
if err := Unmarshal(StringReader(pathTestString), v); err != nil {
|
||||
t.Fatalf("Unmarshal: %s", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user