]> Cypherpunks repositories - gostls13.git/commitdiff
gob: make robust when decoding a struct with non-struct data.
authorRob Pike <r@golang.org>
Sun, 19 Sep 2010 21:37:06 +0000 (07:37 +1000)
committerRob Pike <r@golang.org>
Sun, 19 Sep 2010 21:37:06 +0000 (07:37 +1000)
The decoder was crashing when handling an rpc that expected
a struct but was delivered something else.  This diagnoses the
problem.  The other direction (expecting non-struct but getting
one) was already handled.

R=rsc
CC=golang-dev
https://golang.org/cl/2246041

src/pkg/gob/decode.go
src/pkg/gob/encoder_test.go
src/pkg/gob/type.go

index a70799e9a729997d4770fc670629df3756f98180..5ca9b89cd689e96978e70d5337cb135b33908738 100644 (file)
@@ -843,12 +843,17 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng
                return dec.compileSingle(remoteId, rt)
        }
        var wireStruct *structType
-       // Builtin types can come from global pool; the rest must be defined by the decoder
+       // Builtin types can come from global pool; the rest must be defined by the decoder.
+       // Also we know we're decoding a struct now, so the client must have sent one.
        if t, ok := builtinIdToType[remoteId]; ok {
-               wireStruct = t.(*structType)
+               wireStruct, _ = t.(*structType)
        } else {
                wireStruct = dec.wireType[remoteId].structT
        }
+       if wireStruct == nil {
+               return nil, os.ErrorString("gob: type mismatch in decoder: want struct type " +
+                       rt.String() + "; got non-struct")
+       }
        engine = new(decEngine)
        engine.instr = make([]decInstr, len(wireStruct.field))
        // Loop over the fields of the wire type.
index f5b68113eeb6f86ff1b3daa88e52634a2f935d1d..87627fa2835a4fe025785c8db92e4fbe39ee2a52 100644 (file)
@@ -327,3 +327,31 @@ func TestSingletons(t *testing.T) {
                }
        }
 }
+
+func TestStructNonStruct(t *testing.T) {
+       type Struct struct {
+               a string
+       }
+       type NonStruct string
+       s := Struct{"hello"}
+       var sp Struct
+       if err := encAndDec(s, &sp); err != nil {
+               t.Error(err)
+       }
+       var ns NonStruct
+       if err := encAndDec(s, &ns); err == nil {
+               t.Error("should get error for struct/non-struct")
+       } else if strings.Index(err.String(), "type") < 0 {
+               t.Error("for struct/non-struct expected type error; got", err)
+       }
+       // Now try the other way
+       var nsp NonStruct
+       if err := encAndDec(ns, &nsp); err != nil {
+               t.Error(err)
+       }
+       if err := encAndDec(ns, &s); err == nil {
+               t.Error("should get error for non-struct/struct")
+       } else if strings.Index(err.String(), "type") < 0 {
+               t.Error("for non-struct/struct expected type error; got", err)
+       }
+}
index 0b01b74dc9d0d54137fc47189dadddcdbb15f28a..e6ae499f490eaf263c3be7bf74d4e841adb90a1d 100644 (file)
@@ -52,10 +52,20 @@ func (t typeId) gobType() gobType {
 }
 
 // string returns the string representation of the type associated with the typeId.
-func (t typeId) string() string { return t.gobType().string() }
+func (t typeId) string() string {
+       if t.gobType() == nil {
+               return "<nil>"
+       }
+       return t.gobType().string()
+}
 
 // Name returns the name of the type associated with the typeId.
-func (t typeId) Name() string { return t.gobType().Name() }
+func (t typeId) Name() string {
+       if t.gobType() == nil {
+               return "<nil>"
+       }
+       return t.gobType().Name()
+}
 
 // Common elements of all types.
 type commonType struct {