From abc93250815af37683951eaeef2ad2fc03d8cdf0 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 21 Oct 2026 11:36:17 -0400 Subject: [PATCH] fix: restore conaninfo's host path lookup The conaninfo parser reads the package name and version out of the `////package//conaninfo.txt` layout. It used to read that from the file reference's real path (the absolute host path) and fall back to the location, but the path sweep switched it to `LocalPath()` only. A single file scan, or a directory scan rooted below `.conan/data`, then failed to parse the path and dropped the package. The reference's real path is used first again, falling back to `LocalPath()` (which is what nested archive entries have, since they carry no reference). Signed-off-by: Alex Goodman --- syft/pkg/cataloger/cpp/parse_conaninfo.go | 7 ++++++- .../pkg/cataloger/cpp/parse_conaninfo_test.go | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/cpp/parse_conaninfo.go b/syft/pkg/cataloger/cpp/parse_conaninfo.go index e8586d19c..390b520cb 100644 --- a/syft/pkg/cataloger/cpp/parse_conaninfo.go +++ b/syft/pkg/cataloger/cpp/parse_conaninfo.go @@ -81,7 +81,12 @@ func parseFullRequiresLine(line string, reader file.LocationReadCloser, pkgs *[] // - recipe revision (recipe_hash) func parseConaninfo(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { // First set the base package info by checking the relative path - fullFilePath := reader.LocalPath() + // the reference's real path is the absolute host path, which holds the package layout even when the + // scan is rooted below .conan/data + fullFilePath := string(reader.Reference().RealPath) + if fullFilePath == "" { + fullFilePath = reader.LocalPath() + } mainMetadata, err := parseConanMetadataFromFilePath(fullFilePath) if err != nil { diff --git a/syft/pkg/cataloger/cpp/parse_conaninfo_test.go b/syft/pkg/cataloger/cpp/parse_conaninfo_test.go index 92fbd1342..450dee9a7 100644 --- a/syft/pkg/cataloger/cpp/parse_conaninfo_test.go +++ b/syft/pkg/cataloger/cpp/parse_conaninfo_test.go @@ -1,8 +1,13 @@ package cpp import ( + "context" + "os" "testing" + "github.com/stretchr/testify/require" + + stereoscopeFile "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -126,3 +131,19 @@ func TestParseConaninfo(t *testing.T) { pkgtest.TestFileParser(t, fixture, parseConaninfo, expected, expectedRelationships) } + +func TestParseConaninfo_pathFromTheFileReference(t *testing.T) { + // a scan rooted at the package directory: only the reference's real path has the package layout + fixture := "testdata/conaninfo/mfast/1.2.2/my_user/my_channel/package/9d1f076b471417647c2022a78d5e2c1f834289ac/conaninfo.txt" + f, err := os.Open(fixture) + require.NoError(t, err) + t.Cleanup(func() { _ = f.Close() }) + + ref := stereoscopeFile.NewFileReference(stereoscopeFile.Path("/home/user/.conan/data/mfast/1.2.2/my_user/my_channel/package/9d1f076b471417647c2022a78d5e2c1f834289ac/conaninfo.txt")) + location := file.NewLocationFromDirectory("/conaninfo.txt", "", *ref) + + pkgs, _, err := parseConaninfo(context.Background(), nil, nil, file.NewLocationReadCloser(location, f)) + require.NoError(t, err) + require.NotEmpty(t, pkgs) + require.Equal(t, "mfast", pkgs[len(pkgs)-1].Name) +}