From 6ebd44bb936b77ea6f33d2061b80c93f9d401b9b Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 12 Feb 2021 20:05:44 +0900 Subject: [PATCH 1/2] Fix decoding of pointer of empty interface type --- decode_interface.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/decode_interface.go b/decode_interface.go index a46abe5..3019b05 100644 --- a/decode_interface.go +++ b/decode_interface.go @@ -13,6 +13,12 @@ type interfaceDecoder struct { } func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder { + if typ == emptyInterfaceType { + // If type is the same as emptyInterface ( `interface{}` ), + // the address of `*interface{}` type will be passed when actually decoding, + // so type must be converted to pointer type. + typ = type2rtype(reflect.New(rtype2type(typ)).Type()) + } return &interfaceDecoder{ typ: typ, structName: structName, @@ -32,7 +38,8 @@ func (d *interfaceDecoder) numDecoder(s *stream) decoder { } var ( - interfaceMapType = type2rtype( + emptyInterfaceType = type2rtype(reflect.TypeOf((*interface{})(nil)).Elem()) + interfaceMapType = type2rtype( reflect.TypeOf((*map[string]interface{})(nil)).Elem(), ) stringType = type2rtype( @@ -82,7 +89,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, p unsafe.Pointe stringType, newStringDecoder(d.structName, d.fieldName), interfaceMapType.Elem(), - newInterfaceDecoder(d.typ, d.structName, d.fieldName), + newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), d.structName, d.fieldName, ).decodeStream(s, ptr); err != nil { @@ -94,9 +101,9 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, p unsafe.Pointe var v []interface{} ptr := unsafe.Pointer(&v) if err := newSliceDecoder( - newInterfaceDecoder(d.typ, d.structName, d.fieldName), - d.typ, - d.typ.Size(), + newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), + emptyInterfaceType, + emptyInterfaceType.Size(), d.structName, d.fieldName, ).decodeStream(s, ptr); err != nil { @@ -246,7 +253,7 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor int64, p unsa stringType, newStringDecoder(d.structName, d.fieldName), interfaceMapType.Elem(), - newInterfaceDecoder(d.typ, d.structName, d.fieldName), + newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), d.structName, d.fieldName, ) cursor, err := dec.decode(buf, cursor, ptr) @@ -259,9 +266,9 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor int64, p unsa var v []interface{} ptr := unsafe.Pointer(&v) dec := newSliceDecoder( - newInterfaceDecoder(d.typ, d.structName, d.fieldName), - d.typ, - d.typ.Size(), + newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), + emptyInterfaceType, + emptyInterfaceType.Size(), d.structName, d.fieldName, ) cursor, err := dec.decode(buf, cursor, ptr) From e917f04936bea67ea2b856bb9657253a78b1119b Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Sat, 13 Feb 2021 02:54:42 +0900 Subject: [PATCH 2/2] Fix decoding for nil value of empty interface type --- decode_interface.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/decode_interface.go b/decode_interface.go index 3019b05..f213862 100644 --- a/decode_interface.go +++ b/decode_interface.go @@ -13,12 +13,6 @@ type interfaceDecoder struct { } func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder { - if typ == emptyInterfaceType { - // If type is the same as emptyInterface ( `interface{}` ), - // the address of `*interface{}` type will be passed when actually decoding, - // so type must be converted to pointer type. - typ = type2rtype(reflect.New(rtype2type(typ)).Type()) - } return &interfaceDecoder{ typ: typ, structName: structName, @@ -181,7 +175,7 @@ func (d *interfaceDecoder) decodeStream(s *stream, p unsafe.Pointer) error { iface := rv.Interface() ifaceHeader := (*interfaceHeader)(unsafe.Pointer(&iface)) typ := ifaceHeader.typ - if d.typ == typ || typ == nil { + if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { // concrete type is empty interface return d.decodeStreamEmptyInterface(s, p) } @@ -211,7 +205,7 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (i iface := rv.Interface() ifaceHeader := (*interfaceHeader)(unsafe.Pointer(&iface)) typ := ifaceHeader.typ - if d.typ == typ || typ == nil { + if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { // concrete type is empty interface return d.decodeEmptyInterface(buf, cursor, p) }