From 1ac8861d1c8ad329233b9e5e3f5d8420f7fbdc8d Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Thu, 24 Aug 2023 17:17:51 -0400 Subject: [PATCH 1/3] initial attempt at fix Signed-off-by: Will Murphy --- syft/pkg/cataloger/java/parse_pom_xml.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index f39bef1d636..a2594671d22 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -215,6 +215,9 @@ func resolveProperty(pom gopom.Project, property *string, propertyName string) s pomValue = pomValue.Field(fieldNum) pomValueType = pomValue.Type() if pomValueType.Kind() == reflect.Ptr { + if pomValue.IsNil() { + break + } pomValue = pomValue.Elem() if !pomValue.IsZero() { pomValueType = pomValue.Type() From 8a5bbad5e2eb26e4b5bbffa7ad04059ef7517416 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 25 Aug 2023 09:52:57 -0400 Subject: [PATCH 2/3] fix: stop nil pointer panic in pom reflection A recent update to gopom changed many fields to be omitted when empty, resulting in a number of nil pointers inside the nested structure of the pom that previously didn't exist. Defend against these in the search for the property value. Signed-off-by: Will Murphy --- syft/pkg/cataloger/java/parse_pom_xml.go | 11 +++++++++-- syft/pkg/cataloger/java/parse_pom_xml_test.go | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index a2594671d22..51badeb877e 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -188,7 +188,7 @@ func resolveProperty(pom gopom.Project, property *string, propertyName string) s propertyCase := safeString(property) log.WithFields("existingPropertyValue", propertyCase, "propertyName", propertyName).Trace("resolving property") return propertyMatcher.ReplaceAllStringFunc(propertyCase, func(match string) string { - propertyName := strings.TrimSpace(match[2 : len(match)-1]) + propertyName := strings.TrimSpace(match[2 : len(match)-1]) // remove leading ${ and trailing } entries := pomProperties(pom) if value, ok := entries[propertyName]; ok { return value @@ -211,18 +211,25 @@ func resolveProperty(pom gopom.Project, property *string, propertyName string) s f := pomValueType.Field(fieldNum) tag := f.Tag.Get("xml") tag = strings.TrimSuffix(tag, ",omitempty") + // a segment of the property name matches the xml tag for the field, + // so we need to recurse down the nested structs or return a match + // if we're done. if part == tag { pomValue = pomValue.Field(fieldNum) pomValueType = pomValue.Type() if pomValueType.Kind() == reflect.Ptr { + // we were recursing down the nested structs, but one of the steps + // we need to take is a nil pointer, so give up and return the original match if pomValue.IsNil() { - break + return match } pomValue = pomValue.Elem() if !pomValue.IsZero() { + // we found a non-zero value whose tag matches this part of the property name pomValueType = pomValue.Type() } } + // If this was the last part of the property name, return the value if partNum == numParts-1 { return fmt.Sprintf("%v", pomValue.Interface()) } diff --git a/syft/pkg/cataloger/java/parse_pom_xml_test.go b/syft/pkg/cataloger/java/parse_pom_xml_test.go index 98551452155..9e79fe96e84 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml_test.go +++ b/syft/pkg/cataloger/java/parse_pom_xml_test.go @@ -446,6 +446,24 @@ func Test_resolveProperty(t *testing.T) { }, expected: "org.some.parent", }, + { + name: "nil pointer halts search", + property: "${project.parent.groupId}", + pom: gopom.Project{ + Parent: nil, + }, + expected: "${project.parent.groupId}", + }, + { + name: "nil string pointer halts search", + property: "${project.parent.groupId}", + pom: gopom.Project{ + Parent: &gopom.Parent{ + GroupID: nil, + }, + }, + expected: "${project.parent.groupId}", + }, } for _, test := range tests { From 33fb8edc729e1e12d76832d57889296ef2147207 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 25 Aug 2023 11:46:07 -0400 Subject: [PATCH 3/3] trim tag suffixes besides omitempty Signed-off-by: Will Murphy --- syft/pkg/cataloger/java/parse_pom_xml.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index 51badeb877e..a6f5340cf1f 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -210,7 +210,7 @@ func resolveProperty(pom gopom.Project, property *string, propertyName string) s for fieldNum := 0; fieldNum < pomValueType.NumField(); fieldNum++ { f := pomValueType.Field(fieldNum) tag := f.Tag.Get("xml") - tag = strings.TrimSuffix(tag, ",omitempty") + tag = strings.Split(tag, ",")[0] // a segment of the property name matches the xml tag for the field, // so we need to recurse down the nested structs or return a match // if we're done.