mirror of
https://github.com/golang/go
synced 2024-11-25 04:17:57 -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]
|
instr := &engine.instr[singletonField]
|
||||||
if instr.indir != ut.indir {
|
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
|
ptr := unsafe.Pointer(basep) // offset will be zero
|
||||||
if instr.indir > 1 {
|
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.
|
// getDecEnginePtr returns the engine for the specified type.
|
||||||
func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err error) {
|
func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err error) {
|
||||||
rt := ut.base
|
rt := ut.user
|
||||||
decoderMap, ok := dec.decoderCache[rt]
|
decoderMap, ok := dec.decoderCache[rt]
|
||||||
if !ok {
|
if !ok {
|
||||||
decoderMap = make(map[typeId]**decEngine)
|
decoderMap = make(map[typeId]**decEngine)
|
||||||
|
@ -712,3 +712,27 @@ func TestGobPtrSlices(t *testing.T) {
|
|||||||
t.Fatal("got %v; wanted %v", out, in)
|
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