ugorji / go

idiomatic codec and rpc lib for msgpack, cbor, json, etc. msgpack.org[Go]
MIT License
1.83k stars 294 forks source link

panic / memory corruption when decoding msgpack struct with embedded maps #367

Closed philipatl closed 2 years ago

philipatl commented 2 years ago

Please see my example below. The issue occurs when you have a certain nesting of structs with maps. In this case, we have a struct with a map of string to slice of pointer to struct with a map of string to slice of string. This appears to cause the kMap decode function, which is called recursively, to assign memory where it should not.

package main

import (
    "bytes"
    "fmt"

    "github.com/ugorji/go/codec"
)

type Inner struct {
    InnerMap map[string][]string
}

type Outer struct {
    OuterMap map[string][]*Inner
}

func reproPanic() {
    inner := &Inner{}
    inner.InnerMap = map[string][]string{
        "foo": {
            "bar",
        },
    }

    outer := &Outer{}
    outer.OuterMap = make(map[string][]*Inner)
    outer.OuterMap["blah"] = []*Inner{
        inner,
    }

    outer2 := &Outer{}

    encodeDecodeEncodeRoundtrip(outer, outer2)

    // not expected to get here
    fmt.Printf("NOT REACHED!?")
}

func encodeDecodeEncodeRoundtrip(obj, dest interface{}) {

    handle := &codec.MsgpackHandle{}
    encoder := codec.NewEncoder(nil, handle)
    decoder := codec.NewDecoder(nil, handle)

    buf := bytes.NewBuffer(nil)
    encoder.Reset(buf)
    encoder.MustEncode(obj)

    decoder.Reset(bytes.NewBuffer(buf.Bytes()))
    decoder.MustDecode(dest)

    buf = bytes.NewBuffer(nil)
    encoder.Reset(buf)
    encoder.MustEncode(dest)
}

func main() {
    reproPanic()
}