mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01: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
@ -230,16 +230,26 @@ func cleanDescription(original *string) (cleaned string) {
|
|||||||
// resolveProperty emulates some maven property resolution logic by looking in the project's variables
|
// 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}.
|
// as well as supporting the project expressions like ${project.parent.groupId}.
|
||||||
// If no match is found, the entire expression including ${} is returned
|
// If no match is found, the entire expression including ${} is returned
|
||||||
//
|
|
||||||
//nolint:gocognit
|
|
||||||
func resolveProperty(pom gopom.Project, property *string, propertyName string) string {
|
func resolveProperty(pom gopom.Project, property *string, propertyName string) string {
|
||||||
propertyCase := safeString(property)
|
propertyCase := safeString(property)
|
||||||
log.WithFields("existingPropertyValue", propertyCase, "propertyName", propertyName).Trace("resolving 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 {
|
return propertyMatcher.ReplaceAllStringFunc(propertyCase, func(match string) string {
|
||||||
propertyName := strings.TrimSpace(match[2 : len(match)-1]) // remove leading ${ and trailing }
|
propertyName := strings.TrimSpace(match[2 : len(match)-1]) // remove leading ${ and trailing }
|
||||||
|
if _, seen := seenPropertyNames[propertyName]; seen {
|
||||||
|
return propertyCase
|
||||||
|
}
|
||||||
entries := pomProperties(pom)
|
entries := pomProperties(pom)
|
||||||
if value, ok := entries[propertyName]; ok {
|
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,
|
// 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}",
|
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 {
|
for _, test := range tests {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user