Fix: repeatedly dereference pom variables (#2781)

* Fix: repeatedly dereference pom variables

Previously, if there was more than one layer of variable indirection in
the pom property (propert A says it has the same value as property B,
property B says it has the same value as property C), then Syft would
only dereference one layer. Add a loop to dereference variables until
either dereferencing fails, or until the variable is completely
dereferenced back to a literal.

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* switch to recursive implementation

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* add test cases for degenerate poms

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* switch to recursive implementation

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* remove redundant pieces of test cases

Signed-off-by: Will Murphy <will.murphy@anchore.com>

---------

Signed-off-by: Will Murphy <will.murphy@anchore.com>
This commit is contained in:
William Murphy
2024-04-16 15:44:02 -04:00
committed by GitHub
parent 3b01e13f92
commit 3e71f46fc8
2 changed files with 93 additions and 3 deletions
+13 -3
View File
@@ -230,16 +230,26 @@ func cleanDescription(original *string) (cleaned string) {
// resolveProperty emulates some maven property resolution logic by looking in the project's variables
// as well as supporting the project expressions like ${project.parent.groupId}.
// If no match is found, the entire expression including ${} is returned
//
//nolint:gocognit
func resolveProperty(pom gopom.Project, property *string, propertyName string) string {
propertyCase := safeString(property)
log.WithFields("existingPropertyValue", propertyCase, "propertyName", propertyName).Trace("resolving property")
seenBeforePropertyNames := map[string]struct{}{
propertyName: {},
}
return recursiveResolveProperty(pom, propertyCase, seenBeforePropertyNames)
}
//nolint:gocognit
func recursiveResolveProperty(pom gopom.Project, propertyCase string, seenPropertyNames map[string]struct{}) string {
return propertyMatcher.ReplaceAllStringFunc(propertyCase, func(match string) string {
propertyName := strings.TrimSpace(match[2 : len(match)-1]) // remove leading ${ and trailing }
if _, seen := seenPropertyNames[propertyName]; seen {
return propertyCase
}
entries := pomProperties(pom)
if value, ok := entries[propertyName]; ok {
return value
seenPropertyNames[propertyName] = struct{}{}
return recursiveResolveProperty(pom, value, seenPropertyNames) // recursively resolve in case a variable points to a variable.
}
// if we don't find anything directly in the pom properties,