diff --git a/mapstructure.go b/mapstructure.go index 9087fd96..43f325a0 100644 --- a/mapstructure.go +++ b/mapstructure.go @@ -1625,6 +1625,13 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e case reflect.Ptr: if fieldVal.Type().Elem().Kind() == reflect.Struct { if fieldVal.IsNil() { + if !fieldVal.CanSet() { + errs = append(errs, newDecodeError( + name+"."+fieldType.Name, + fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()), + )) + continue + } fieldVal.Set(reflect.New(fieldVal.Type().Elem())) } structs = append(structs, fieldVal.Elem()) diff --git a/mapstructure_test.go b/mapstructure_test.go index baf40dfe..96ee5e97 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go @@ -917,6 +917,33 @@ func TestDecode_EmbeddedPointerSquash_WithoutPreInitializedStructs_FromMapToStru } } +type EmbeddedUnexportedPointerSquash struct { + *embeddedUnexported `mapstructure:",squash"` + Vunique string +} + +type embeddedUnexported struct { + Vstring string +} + +func TestDecode_EmbeddedUnexportedPointerSquash_FromMapToStruct(t *testing.T) { + t.Parallel() + + input := map[string]any{ + "Vstring": "foo", + "Vunique": "bar", + } + + result := EmbeddedUnexportedPointerSquash{} + err := Decode(input, &result) + if err == nil { + t.Fatal("expected an error decoding into an unexported embedded pointer squash, got nil") + } + if !strings.Contains(err.Error(), "unsupported type for squash") { + t.Fatalf("unexpected error message: %s", err) + } +} + func TestDecode_EmbeddedPointerSquashWithNestedMapstructure_FromStructToMap(t *testing.T) { t.Parallel()