Skip to content

Commit

Permalink
Merge pull request #5 from go-viper/fix-pointer-deref
Browse files Browse the repository at this point in the history
Dereference multiple pointers when decoding to maps
  • Loading branch information
sagikazarmark authored Dec 18, 2023
2 parents 8244341 + efd7fa4 commit 69bb54a
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 1 deletion.
8 changes: 7 additions & 1 deletion mapstructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,8 +811,14 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
valMap = reflect.MakeMap(mapType)
}

dataVal := reflect.ValueOf(data)

// Resolve any levels of indirection
for dataVal.Kind() == reflect.Pointer {
dataVal = reflect.Indirect(dataVal)
}

// Check input type and based on the input type jump to the proper func
dataVal := reflect.Indirect(reflect.ValueOf(data))
switch dataVal.Kind() {
case reflect.Map:
return d.decodeMapFromMap(name, dataVal, val, valMap)
Expand Down
107 changes: 107 additions & 0 deletions mapstructure_bugs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,3 +638,110 @@ func TestDecode_nonComparableType(t *testing.T) {
t.Fatalf("fail: %#v", decodeTo.NonComparableType)
}
}

// GH-347: Decoding maps with multiple indirection results in an error
func TestDecodeToMapWithMultipleIndirection(t *testing.T) {
t.Run("Struct", func(t *testing.T) {
type Struct struct {
Foo string `mapstructure:"foo"`
}

v := Struct{
Foo: "bar",
}

i := &v
ii := &i
iii := &ii

var actual map[string]interface{}

if err := Decode(iii, &actual); err != nil {
t.Fatal(err)
}

expected := map[string]interface{}{
"foo": "bar",
}

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected: %#v, got: %#v", expected, actual)
}
})

t.Run("Map", func(t *testing.T) {
v := map[string]interface{}{
"foo": "bar",
}

i := &v
ii := &i
iii := &ii

var actual map[string]interface{}

if err := Decode(iii, &actual); err != nil {
t.Fatal(err)
}

expected := map[string]interface{}{
"foo": "bar",
}

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected: %#v, got: %#v", expected, actual)
}
})

t.Run("Array", func(t *testing.T) {
v := [1]map[string]interface{}{
{
"foo": "bar",
},
}

i := &v
ii := &i
iii := &ii

var actual map[string]interface{}

if err := WeakDecode(iii, &actual); err != nil {
t.Fatal(err)
}

expected := map[string]interface{}{
"foo": "bar",
}

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected: %#v, got: %#v", expected, actual)
}
})

t.Run("Slice", func(t *testing.T) {
v := []map[string]interface{}{
{
"foo": "bar",
},
}

i := &v
ii := &i
iii := &ii

var actual map[string]interface{}

if err := WeakDecode(iii, &actual); err != nil {
t.Fatal(err)
}

expected := map[string]interface{}{
"foo": "bar",
}

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected: %#v, got: %#v", expected, actual)
}
})
}

0 comments on commit 69bb54a

Please sign in to comment.