From 7985840da4ad23157a8726e6cf3b24a026f500e1 Mon Sep 17 00:00:00 2001 From: NicklasWallgren Date: Tue, 10 Jan 2023 15:46:58 +0100 Subject: [PATCH] Fixed panic with nested pointer structs --- copier.go | 12 +++++++++++- copier_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/copier.go b/copier.go index c699d70..0d21d14 100644 --- a/copier.go +++ b/copier.go @@ -270,7 +270,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) } srcFieldName, destFieldName := getFieldName(name, flgs) - if fromField := source.FieldByName(srcFieldName); fromField.IsValid() && !shouldIgnore(fromField, opt.IgnoreEmpty) { + if fromField := fieldByNameOrZeroValue(source, srcFieldName); fromField.IsValid() && !shouldIgnore(fromField, opt.IgnoreEmpty) { // process for nested anonymous field destFieldNotSet := false if f, ok := dest.Type().FieldByName(destFieldName); ok { @@ -400,6 +400,16 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) return } +func fieldByNameOrZeroValue(source reflect.Value, fieldName string) (value reflect.Value) { + defer func() { + if err := recover(); err != nil { + value = reflect.Value{} + } + }() + + return source.FieldByName(fieldName) +} + func copyUnexportedStructFields(to, from reflect.Value) { if from.Kind() != reflect.Struct || to.Kind() != reflect.Struct || !from.Type().AssignableTo(to.Type()) { return diff --git a/copier_test.go b/copier_test.go index 08db7f3..de8dff8 100644 --- a/copier_test.go +++ b/copier_test.go @@ -1732,3 +1732,33 @@ func TestEmptySlice(t *testing.T) { t.Error("from should be empty slice nil") } } + +func TestNestedNilPointerStruct(t *testing.T) { + type destination struct { + Title string + } + + type NestedSource struct { + ID int + } + + type source struct { + Title string + *NestedSource + } + + from := &source{ + Title: "A title to be copied", + } + + to := destination{} + + err := copier.Copy(&to, from) + if err != nil { + t.Error("should not error") + } + + if from.Title != to.Title { + t.Errorf("to (%v) value should equal from (%v) value", to.Title, from.Title) + } +}