mirror of
https://github.com/golang/go
synced 2024-11-25 00:17:58 -07:00
encoding/gob: cache engine for user type, not base type
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
This commit is contained in:
parent
7737e19b15
commit
420f713b7a
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user