]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/gob: cache engine for user type, not base type
authorRob Pike <r@golang.org>
Sat, 18 Feb 2012 03:38:37 +0000 (14:38 +1100)
committerRob Pike <r@golang.org>
Sat, 18 Feb 2012 03:38:37 +0000 (14:38 +1100)
When we build the encode engine for a recursive type, we
mustn't disregard the indirections or we can try to reuse an
engine at the wrong indirection level.

Fixes #3026.

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5675087

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

index b7f3e2420e031b0b8b3be61c3cde9a63357aa151..a0bb985300f3b32adc784254f12bf7a250eb71ab 100644 (file)
@@ -473,7 +473,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
        }
        instr := &engine.instr[singletonField]
        if instr.indir != ut.indir {
-               errorf("gob: internal error: inconsistent indirection instr %d ut %d", 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
        if instr.indir > 1 {
@@ -1149,7 +1149,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
 
 // getDecEnginePtr returns the engine for the specified type.
 func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err error) {
-       rt := ut.base
+       rt := ut.user
        decoderMap, ok := dec.decoderCache[rt]
        if !ok {
                decoderMap = make(map[typeId]**decEngine)
index 7911dad90da14bccd204f7eb6ade2f5dd479902f..3bfae30f39a88b8fafe2364602c563c784d2d896 100644 (file)
@@ -712,3 +712,27 @@ func TestGobPtrSlices(t *testing.T) {
                t.Fatal("got %v; wanted %v", out, in)
        }
 }
+
+// getDecEnginePtr cached engine for ut.base instead of ut.user so we passed
+// a *map and then tried to reuse its engine to decode the inner map.
+func TestPtrToMapOfMap(t *testing.T) {
+       Register(make(map[string]interface{}))
+       subdata := make(map[string]interface{})
+       subdata["bar"] = "baz"
+       data := make(map[string]interface{})
+       data["foo"] = subdata
+
+       b := new(bytes.Buffer)
+       err := NewEncoder(b).Encode(data)
+       if err != nil {
+               t.Fatal("encode:", err)
+       }
+       var newData map[string]interface{}
+       err = NewDecoder(b).Decode(&newData)
+       if err != nil {
+               t.Fatal("decode:", err)
+       }
+       if !reflect.DeepEqual(data, newData) {
+               t.Fatalf("expected %v got %v", data, newData)
+       }
+}