From e58050bac045be672621047d5699b88884e2da62 Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Fri, 20 Jan 2023 09:49:44 -0500 Subject: [PATCH] Fix panic in apkdb parsing on empty "provides" values (#1494) * Add failing test for strip version specifiers panic Signed-off-by: Dan Luhring * Fix test Signed-off-by: Dan Luhring * Prevent panic scenario in helper func Signed-off-by: Dan Luhring * Fix lint issue Signed-off-by: Dan Luhring * add tests for apk stripVersionSpecifier() and remove caller empty value check Signed-off-by: Alex Goodman Signed-off-by: Dan Luhring Signed-off-by: Alex Goodman Co-authored-by: Alex Goodman --- syft/pkg/cataloger/apkdb/parse_apk_db.go | 8 ++- syft/pkg/cataloger/apkdb/parse_apk_db_test.go | 60 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/apkdb/parse_apk_db.go b/syft/pkg/cataloger/apkdb/parse_apk_db.go index f814a2e32a3..b5a5be32128 100644 --- a/syft/pkg/cataloger/apkdb/parse_apk_db.go +++ b/syft/pkg/cataloger/apkdb/parse_apk_db.go @@ -361,5 +361,11 @@ func stripVersionSpecifier(s string) string { // examples: // musl>=1 --> musl // cmd:scanelf=1.3.4-r0 --> cmd:scanelf - return splitAny(s, "<>=")[0] + + items := splitAny(s, "<>=") + if len(items) == 0 { + return s + } + + return items[0] } diff --git a/syft/pkg/cataloger/apkdb/parse_apk_db_test.go b/syft/pkg/cataloger/apkdb/parse_apk_db_test.go index 2e963b1c12a..707c2d46ed8 100644 --- a/syft/pkg/cataloger/apkdb/parse_apk_db_test.go +++ b/syft/pkg/cataloger/apkdb/parse_apk_db_test.go @@ -911,6 +911,27 @@ func Test_discoverPackageDependencies(t *testing.T) { } }, }, + { + name: "strip version specifiers with empty provides value", + genFn: func() ([]pkg.Package, []artifact.Relationship) { + a := pkg.Package{ + Name: "package-a", + Metadata: pkg.ApkMetadata{ + Dependencies: []string{"so:libc.musl-x86_64.so.1"}, + }, + } + a.SetID() + b := pkg.Package{ + Name: "package-b", + Metadata: pkg.ApkMetadata{ + Provides: []string{""}, + }, + } + b.SetID() + + return []pkg.Package{a, b}, nil + }, + }, { name: "depends on package name", genFn: func() ([]pkg.Package, []artifact.Relationship) { @@ -1126,3 +1147,42 @@ func newLocationReadCloser(t *testing.T, path string) source.LocationReadCloser return source.NewLocationReadCloser(source.NewLocation(path), f) } + +func Test_stripVersionSpecifier(t *testing.T) { + tests := []struct { + name string + version string + want string + }{ + { + name: "empty expression", + version: "", + want: "", + }, + { + name: "no expression", + version: "cmd:foo", + want: "cmd:foo", + }, + { + name: "=", + version: "cmd:scanelf=1.3.4-r0", + want: "cmd:scanelf", + }, + { + name: ">=", + version: "cmd:scanelf>=1.3.4-r0", + want: "cmd:scanelf", + }, + { + name: "<", + version: "cmd:scanelf<1.3.4-r0", + want: "cmd:scanelf", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, stripVersionSpecifier(tt.version)) + }) + } +}