ugorji / go

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

Infinite cycle with json StringToRaw=true and custom encoder #316

Closed Albibek closed 4 years ago

Albibek commented 5 years ago

Hello.

Found an issue when encoding json falls to infinite cycle and then crashes with stack overflow.

Seems like returning a string from converter makes this string required to be interpreted as raw bytes again and going back to converter again.


import (
    "log"

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

type DumbRawConverterExt struct{}

func (c DumbRawConverterExt) ConvertExt(v interface{}) interface{} {
    switch v.(type) {
    case []byte:
        // there may be some custom escaping for raw bytes here
        // but even returning an empty string gives cycling
        return string(v.([]byte))
        //return ""
    default:
        return v
    }

}

func (c DumbRawConverterExt) UpdateExt(src, dst interface{}) {
    return
}

func main() {
    var err error
    // bad unicode
    a := []byte{0x0a, 0x80, 0x61, 0x00}

    m := map[string]interface{}{
        "somekey1": string(a),
        "somekey2": a,
    }

    jhandle := &codec.JsonHandle{
        MapKeyAsString: true,
        RawBytesExt:    DumbRawConverterExt{},
    }

    // setting this gives cycle
    jhandle.EncodeOptions.StringToRaw = true
    // c hanging to this works
    //jhandle.EncodeOptions.StringToRaw = false

    buf := make([]byte, 0, 1024)
    jenc := codec.NewEncoderBytes(&buf, jhandle)
    err = jenc.Encode(&m)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("JSON: %#v %s", buf, string(buf))

}
vadv commented 4 years ago

i have the same problem

ugorji commented 4 years ago

I think this is fixable by the library user. If you tell the library to convert strings to []bytes, and then have an extension that converts []byte to string, then you are asking for an infinite loop. Fixing this in the library may be more work than necessary. The library user should fix it.