fix(rpm): keep the epoch when parsing RPM manifest packages (#5201)

---------

Signed-off-by: Sueun Cho <sueun.dev@gmail.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
Sueun Cho 2026-08-22 03:47:23 +09:00 committed by GitHub
parent 34ef7dcbfe
commit 93cf89363b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 97 additions and 7 deletions

View File

@ -59,17 +59,14 @@ func newMetadataFromManifestLine(entry string) (*pkg.RpmDBEntry, error) {
version := versionParts[0] version := versionParts[0]
release := versionParts[1] 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 var epoch *int
if err != nil || parts[5] == "(none)" { if parts[5] != "(none)" {
epoch = nil epoch = parseEpoch(parts[8])
} else {
epoch = &converted
} }
converted, err = strconv.Atoi(parts[6])
var size int var size int
if err == nil { if converted, err := strconv.Atoi(parts[6]); err == nil {
size = converted size = converted
} }
return &pkg.RpmDBEntry{ return &pkg.RpmDBEntry{

View File

@ -1,8 +1,12 @@
package redhat package redhat
import ( import (
"strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
@ -80,6 +84,23 @@ func TestParseRpmManifest(t *testing.T) {
Vendor: "Microsoft Corporation", 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(). pkgtest.NewCatalogTester().
@ -88,3 +109,74 @@ func TestParseRpmManifest(t *testing.T) {
TestParser(t, parseRpmManifest) 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)
})
}
}

View File

@ -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 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 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 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