diff --git a/syft/pkg/cataloger/redhat/package.go b/syft/pkg/cataloger/redhat/package.go index fc2da4fd1..1fcbeaf1b 100644 --- a/syft/pkg/cataloger/redhat/package.go +++ b/syft/pkg/cataloger/redhat/package.go @@ -59,17 +59,14 @@ func newMetadataFromManifestLine(entry string) (*pkg.RpmDBEntry, error) { version := versionParts[0] release := versionParts[1] - converted, err := strconv.Atoi(parts[8]) + // EPOCH is "(none)" when the package has no epoch; EPOCHNUM is the numeric form ("0" in that case) var epoch *int - if err != nil || parts[5] == "(none)" { - epoch = nil - } else { - epoch = &converted + if parts[5] != "(none)" { + epoch = parseEpoch(parts[8]) } - converted, err = strconv.Atoi(parts[6]) var size int - if err == nil { + if converted, err := strconv.Atoi(parts[6]); err == nil { size = converted } return &pkg.RpmDBEntry{ diff --git a/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go b/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go index fdc80dce5..5c1f2004f 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go @@ -1,8 +1,12 @@ package redhat import ( + "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" @@ -80,6 +84,23 @@ func TestParseRpmManifest(t *testing.T) { Vendor: "Microsoft Corporation", }, }, + { + Name: "vim", + Version: "2:9.0-1.cm2", + PURL: "pkg:rpm/vim@9.0-1.cm2?arch=x86_64&epoch=2&upstream=vim-9.0-1.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Metadata: pkg.RpmDBEntry{ + Name: "vim", + Epoch: intRef(2), + Arch: "x86_64", + Release: "1.cm2", + Version: "9.0", + SourceRpm: "vim-9.0-1.cm2.src.rpm", + Size: 45000, + Vendor: "Microsoft Corporation", + }, + }, } pkgtest.NewCatalogTester(). @@ -88,3 +109,74 @@ func TestParseRpmManifest(t *testing.T) { TestParser(t, parseRpmManifest) } + +func TestNewMetadataFromManifestLine(t *testing.T) { + // fields are: NAME, VERSION-RELEASE, INSTALLTIME, BUILDTIME, VENDOR, EPOCH, SIZE, ARCH, EPOCHNUM, SOURCERPM + line := func(epoch, size, epochNum string) string { + return strings.Join([]string{ + "vim", "9.0-1.cm2", "1653816591", "1653753130", "Microsoft Corporation", + epoch, size, "x86_64", epochNum, "vim-9.0-1.cm2.src.rpm", + }, "\t") + } + + tests := []struct { + name string + entry string + wantEpoch *int + wantSize int + wantErr require.ErrorAssertionFunc + }{ + { + name: "no epoch", + entry: line("(none)", "45000", "0"), + wantEpoch: nil, + wantSize: 45000, + }, + { + name: "explicit zero epoch is distinct from no epoch", + entry: line("0", "45000", "0"), + wantEpoch: intRef(0), + wantSize: 45000, + }, + { + name: "unparsable epochnum yields no epoch", + entry: line("2", "45000", ""), + wantEpoch: nil, + wantSize: 45000, + }, + { + name: "unparsable size yields zero size", + entry: line("2", "bogus", "2"), + wantEpoch: intRef(2), + wantSize: 0, + }, + { + name: "too few fields", + entry: "vim\t9.0-1.cm2", + wantErr: require.Error, + }, + { + name: "version field missing the release", + entry: strings.Replace(line("(none)", "45000", "0"), "9.0-1.cm2", "9.0", 1), + wantErr: require.Error, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.wantErr == nil { + tt.wantErr = require.NoError + } + + metadata, err := newMetadataFromManifestLine(tt.entry) + tt.wantErr(t, err) + if err != nil { + return + } + + require.NotNil(t, metadata) + assert.Equal(t, tt.wantEpoch, metadata.Epoch) + assert.Equal(t, tt.wantSize, metadata.Size) + }) + } +} diff --git a/syft/pkg/cataloger/redhat/testdata/container-manifest-2 b/syft/pkg/cataloger/redhat/testdata/container-manifest-2 index 1b934cd2c..5a95aedaa 100644 --- a/syft/pkg/cataloger/redhat/testdata/container-manifest-2 +++ b/syft/pkg/cataloger/redhat/testdata/container-manifest-2 @@ -2,4 +2,5 @@ mariner-release 2.0-12.cm2 1653816591 1653753130 Microsoft Corporation (none) 58 filesystem 1.1-9.cm2 1653816591 1653628924 Microsoft Corporation (none) 7596 x86_64 0 filesystem-1.1-9.cm2.src.rpm glibc 2.35-2.cm2 1653816591 1653628955 Microsoft Corporation (none) 10855265 x86_64 0 glibc-2.35-2.cm2.src.rpm openssl-libs 1.1.1k-15.cm2 1653816591 1653631609 Microsoft Corporation (none) 4365048 x86_64 0 openssl-1.1.1k-15.cm2.src.rpm +vim 9.0-1.cm2 1653816591 1653753130 Microsoft Corporation 2 45000 x86_64 2 vim-9.0-1.cm2.src.rpm