You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
type TestObject struct {
Type int
Data interface{}
}
type TestData struct {
Val1 int
Val2 int
}
func TestMsgPackDecoderCacheBugs(t *testing.T) {
var test1 = []*TestData{
{
Val1: 1001,
Val2: 2002,
},
{
Val1: 1003,
Val2: 2004,
},
}
bytes, err := msgpack.Marshal(test1)
if err != nil {
t.Fatalf("unexpected error:%s", err.Error())
}
var decodeVal []msgpack.RawMessage
if err = msgpack.Unmarshal(bytes, &decodeVal); err != nil {
t.Fatalf("unexpected error:%s", err.Error())
}
for idx, rawMsg := range decodeVal {
testVal := TestData{}
if err = msgpack.Unmarshal(rawMsg, &testVal); err != nil {
t.Fatalf("unexpected error:%s", err.Error())
}
t.Logf("index:%d => %#v", idx, testVal)
}
var val = &TestObject{
Type: 1,
//Data is nil will panic reflect: reflect.Value.Set using unaddressable value
Data: nil,
}
bytes2, err := msgpack.Marshal(val)
if err != nil {
t.Fatalf("unexpected error:%s", err.Error())
}
var decodeVal2 = TestObject{
Type: 1,
Data: &msgpack.RawMessage{},
}
if err = msgpack.Unmarshal(bytes2, &decodeVal2); err != nil {
t.Fatalf("unexpected error:%s", err.Error())
}
}
Context (Environment)
go 1.16.3
Detailed Description
1. typeDecMap.Load(typ.Elem()) return wrong decoder before custom decoder
func _getDecoder(typ reflect.Type) decoderFunc {
kind := typ.Kind()
if kind == reflect.Ptr {
//here if value is &msgpack.RawMessage, and will use cache msgpack.RawMessage=>ptrValueDecoder, then goto ptrValueDecoder and v can't set will panic error
if _, ok := typeDecMap.Load(typ.Elem()); ok {
return ptrValueDecoder(typ)
}
}
// value implements speical decodertype should before typeDecMap cache process
if typ.Implements(customDecoderType) {
return nilAwareDecoder(typ, decodeCustomValue)
}
if typ.Implements(unmarshalerType) {
return nilAwareDecoder(typ, unmarshalValue)
}
if typ.Implements(binaryUnmarshalerType) {
return nilAwareDecoder(typ, unmarshalBinaryValue)
}
if typ.Implements(textUnmarshalerType) {
return nilAwareDecoder(typ, unmarshalTextValue)
}
.....
}
2. if has nil code and v can't set such as (&msgpack.RawMesssage{}) value will panic
func ptrValueDecoder(typ reflect.Type) decoderFunc {
decoder := getDecoder(typ.Elem())
return func(d *Decoder, v reflect.Value) error {
if d.hasNilCode() {
//v is &msgpack.RawMesssage can't set, add v.CanSet() check
if !v.IsNil() {
v.Set(reflect.Zero(v.Type()))
}
return d.DecodeNil()
}
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
return decoder(d, v.Elem())
}
}
Possible Implementation
see Detailed Description
The text was updated successfully, but these errors were encountered:
Issue tracker is used for reporting bugs and discussing new features. Please use
Discord or stackoverflow for supporting
issues.
Expected Behavior
no panic and unmarshal success
Current Behavior
Possible Solution
see pr
#309
Steps to Reproduce
Context (Environment)
go 1.16.3
Detailed Description
1. typeDecMap.Load(typ.Elem()) return wrong decoder before custom decoder
2. if has nil code and v can't set such as (&msgpack.RawMesssage{}) value will panic
Possible Implementation
see Detailed Description
The text was updated successfully, but these errors were encountered: