From 9abdb174d50cc6ff03bd963834171750e7cbb227 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 26 Mar 2021 13:18:23 -0400 Subject: [PATCH] ensure pkg.Catalog path index deduplicates real vs virtual paths Signed-off-by: Alex Goodman --- syft/pkg/catalog.go | 9 ++++++-- syft/pkg/catalog_test.go | 48 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/syft/pkg/catalog.go b/syft/pkg/catalog.go index 40af8c851..c6cf47c77 100644 --- a/syft/pkg/catalog.go +++ b/syft/pkg/catalog.go @@ -4,6 +4,8 @@ import ( "sort" "sync" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/log" ) @@ -82,12 +84,15 @@ func (c *Catalog) Add(p Package) { c.idsByType[p.Type] = append(c.idsByType[p.Type], p.ID) // store by file location paths + observedPaths := internal.NewStringSet() for _, l := range p.Locations { - if l.RealPath != "" { + if l.RealPath != "" && !observedPaths.Contains(l.RealPath) { c.idsByPath[l.RealPath] = append(c.idsByPath[l.RealPath], p.ID) + observedPaths.Add(l.RealPath) } - if l.VirtualPath != "" { + if l.VirtualPath != "" && l.RealPath != l.VirtualPath && !observedPaths.Contains(l.VirtualPath) { c.idsByPath[l.VirtualPath] = append(c.idsByPath[l.VirtualPath], p.ID) + observedPaths.Add(l.VirtualPath) } } } diff --git a/syft/pkg/catalog_test.go b/syft/pkg/catalog_test.go index bb02bbc8a..a11c238ae 100644 --- a/syft/pkg/catalog_test.go +++ b/syft/pkg/catalog_test.go @@ -155,3 +155,51 @@ func assertIndexes(t *testing.T, c *Catalog, expectedIndexes expectedIndexes) { } } } + +func TestCatalog_PathIndexDeduplicatesRealVsVirtualPaths(t *testing.T) { + tests := []struct { + name string + pkg Package + }{ + { + name: "multiple locations with shared path", + pkg: Package{ + ID: "my-id", + Locations: []source.Location{ + { + RealPath: "/b/path", + VirtualPath: "/another/path", + }, + { + RealPath: "/b/path", + VirtualPath: "/b/path", + }, + }, + Type: RpmPkg, + }, + }, + { + name: "one location with shared path", + pkg: Package{ + ID: "my-id", + Locations: []source.Location{ + { + RealPath: "/b/path", + VirtualPath: "/b/path", + }, + }, + Type: RpmPkg, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual := NewCatalog(test.pkg).PackagesByPath("/b/path") + if len(actual) != 1 { + t.Errorf("expected exactly one package path, got %d", len(actual)) + } + }) + } + +}