mirror of
https://github.com/anchore/syft
synced 2024-11-10 06:14:16 +00:00
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:
parent
3b01e13f92
commit
3e71f46fc8
2 changed files with 93 additions and 3 deletions
|
@ -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,
|
||||
|
|
|
@ -514,6 +514,86 @@ func Test_resolveProperty(t *testing.T) {
|
|||
},
|
||||
expected: "${project.parent.groupId}",
|
||||
},
|
||||
{
|
||||
name: "double dereference",
|
||||
property: "${springboot.version}",
|
||||
pom: gopom.Project{
|
||||
Parent: &gopom.Parent{
|
||||
Version: stringPointer("1.2.3"),
|
||||
},
|
||||
Properties: &gopom.Properties{
|
||||
Entries: map[string]string{
|
||||
"springboot.version": "${project.parent.version}",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "map missing stops double dereference",
|
||||
property: "${springboot.version}",
|
||||
pom: gopom.Project{
|
||||
Parent: &gopom.Parent{
|
||||
Version: stringPointer("1.2.3"),
|
||||
},
|
||||
},
|
||||
expected: "${springboot.version}",
|
||||
},
|
||||
{
|
||||
name: "resolution halts even if it resolves to a variable",
|
||||
property: "${springboot.version}",
|
||||
pom: gopom.Project{
|
||||
Parent: &gopom.Parent{
|
||||
Version: stringPointer("${undefined.version}"),
|
||||
},
|
||||
Properties: &gopom.Properties{
|
||||
Entries: map[string]string{
|
||||
"springboot.version": "${project.parent.version}",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "${undefined.version}",
|
||||
},
|
||||
{
|
||||
name: "resolution halts even if cyclic",
|
||||
property: "${springboot.version}",
|
||||
pom: gopom.Project{
|
||||
Properties: &gopom.Properties{
|
||||
Entries: map[string]string{
|
||||
"springboot.version": "${springboot.version}",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "${springboot.version}",
|
||||
},
|
||||
{
|
||||
name: "resolution halts even if cyclic more steps",
|
||||
property: "${cyclic.version}",
|
||||
pom: gopom.Project{
|
||||
Properties: &gopom.Properties{
|
||||
Entries: map[string]string{
|
||||
"other.version": "${cyclic.version}",
|
||||
"springboot.version": "${other.version}",
|
||||
"cyclic.version": "${springboot.version}",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "${cyclic.version}",
|
||||
},
|
||||
{
|
||||
name: "resolution halts even if cyclic involving parent",
|
||||
property: "${cyclic.version}",
|
||||
pom: gopom.Project{
|
||||
Properties: &gopom.Properties{
|
||||
Entries: map[string]string{
|
||||
"other.version": "${cyclic.version}",
|
||||
"springboot.version": "${other.version}",
|
||||
"cyclic.version": "${springboot.version}",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "${cyclic.version}",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
Loading…
Reference in a new issue