Skip to content

Commit

Permalink
fix issue 356 that ref to wrong type of map for nil value (#357)
Browse files Browse the repository at this point in the history
* fix issue 356

* fix issue 356

* fix issue 356
  • Loading branch information
tiltwind committed Apr 9, 2023
1 parent 76ae75b commit 33f7e9d
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 13 deletions.
2 changes: 1 addition & 1 deletion map.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (e *Encoder) encMap(m interface{}) error {

value = UnpackPtrValue(value)
// check nil map
if value.Kind() == reflect.Ptr && !value.Elem().IsValid() {
if value.IsNil() || (value.Kind() == reflect.Ptr && !value.Elem().IsValid()) {
e.buffer = EncNull(e.buffer)
return nil
}
Expand Down
29 changes: 17 additions & 12 deletions ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import (
// Empty slice is not nil, but the addresses of all empty slice are the same.
var _emptySliceAddr = unsafe.Pointer(reflect.ValueOf([]interface{}{}).Pointer())

// The addresses of all nil map are the same.
var _nilMapAddr = unsafe.Pointer(reflect.ValueOf(map[interface{}]interface{}(nil)).Pointer())

// used to ref object,list,map
type _refElem struct {
// record the kind of target, objects are the same only if the address and kind are the same
Expand Down Expand Up @@ -127,20 +130,22 @@ func (e *Encoder) checkRefMap(v reflect.Value) (int, bool) {
}
}

if addr != _emptySliceAddr {
if elem, ok := e.refMap[addr]; ok {
if elem.kind == kind {
// If kind is not struct, just return the index. Otherwise,
// check whether the types are same, because the different
// empty struct may share the same address and kind.
if elem.kind != reflect.Struct {
return elem.index, ok
} else if elem.tp == tp {
return elem.index, ok
}
if addr == _emptySliceAddr || addr == _nilMapAddr {
return 0, false
}

if elem, ok := e.refMap[addr]; ok {
if elem.kind == kind {
// If kind is not struct, just return the index. Otherwise,
// check whether the types are same, because the different
// empty struct may share the same address and kind.
if elem.kind != reflect.Struct {
return elem.index, ok
} else if elem.tp == tp {
return elem.index, ok
}
return 0, false
}
return 0, false
}

n := len(e.refMap)
Expand Down
68 changes: 68 additions & 0 deletions testcases/issue356/issue356_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package issue356

import (
"reflect"
"testing"
)

import (
hessian "github.com/apache/dubbo-go-hessian2"
)

import (
"github.com/stretchr/testify/assert"
)

type UserInfo struct {
Name string
Address map[string]string
Family map[string]int
}

func (UserInfo) JavaClassName() string {
return "com.test.UserInfo"
}

func TestIssue356Case(t *testing.T) {
info := &UserInfo{
Name: "test",
Address: nil,
Family: nil,
}

hessian.RegisterPOJO(info)

encoder := hessian.NewEncoder()
err := encoder.Encode(info)
if err != nil {
t.Error(err)
return
}

enBuf := encoder.Buffer()

decoder := hessian.NewDecoder(enBuf)
dec, err := decoder.Decode()
assert.Nil(t, err)

t.Log(dec)

assert.True(t, reflect.DeepEqual(info, dec))
}

0 comments on commit 33f7e9d

Please sign in to comment.