diff --git a/syft/pkg/cataloger/lua/parse_rockspec.go b/syft/pkg/cataloger/lua/parse_rockspec.go index f49107688..82646aa67 100644 --- a/syft/pkg/cataloger/lua/parse_rockspec.go +++ b/syft/pkg/cataloger/lua/parse_rockspec.go @@ -74,6 +74,11 @@ func parseRockspec(ctx context.Context, resolver file.Resolver, _ *generic.Envir } } + if name == "" { + log.WithFields("path", reader.Path()).Trace("rockspec has no package name, skipping") + return nil, nil, nil + } + p := newLuaRocksPackage( ctx, resolver, diff --git a/syft/pkg/cataloger/lua/parse_rockspec_test.go b/syft/pkg/cataloger/lua/parse_rockspec_test.go index f97ecc866..7fdc33c04 100644 --- a/syft/pkg/cataloger/lua/parse_rockspec_test.go +++ b/syft/pkg/cataloger/lua/parse_rockspec_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -144,6 +145,31 @@ func TestParseRockspec(t *testing.T) { }, }, }, + { + // a build block before the package/version fields must not truncate the parse + Fixture: "testdata/rockspec/build-first-1.0-1.rockspec", + ExpectedPkg: pkg.Package{ + Name: "foo", + Version: "1.0-1", + PURL: "pkg:luarocks/foo@1.0-1", + Type: pkg.LuaRocksPkg, + Language: pkg.Lua, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "MIT", file.NewLocation("testdata/rockspec/build-first-1.0-1.rockspec")), + ), + Metadata: pkg.LuaRocksPackage{ + Name: "foo", + Version: "1.0-1", + License: "MIT", + Homepage: "https://github.com/example/foo", + Description: "an example rock", + URL: "git+https://github.com/example/foo.git", + Dependencies: map[string]string{ + "lua": ">= 5.1", + }, + }, + }, + }, } for _, test := range tests { @@ -154,6 +180,25 @@ func TestParseRockspec(t *testing.T) { } } +func TestParseRockspec_noPackageName(t *testing.T) { + // an empty or whitespace-only rockspec has no package name, so it should + // yield no packages and no error rather than a nameless package + fixtures := []string{ + "testdata/rockspec/empty.rockspec", + "testdata/rockspec/whitespace-only.rockspec", + } + + for _, fixture := range fixtures { + t.Run(fixture, func(t *testing.T) { + pkgtest.NewCatalogTester(). + FromFile(t, fixture). + WithErrorAssertion(require.NoError). + Expects(nil, nil). + TestParser(t, parseRockspec) + }) + } +} + func Test_corruptRockspec(t *testing.T) { pkgtest.NewCatalogTester(). FromFile(t, "testdata/corrupt/bad-1.23.0-0.rockspec"). diff --git a/syft/pkg/cataloger/lua/rockspec_parser.go b/syft/pkg/cataloger/lua/rockspec_parser.go index be8630293..14317b5f0 100644 --- a/syft/pkg/cataloger/lua/rockspec_parser.go +++ b/syft/pkg/cataloger/lua/rockspec_parser.go @@ -548,11 +548,11 @@ func skipBuildNode(data []byte, i *int) { bracesCount-- } + *i++ + if bracesCount == 0 { return } - - *i++ } } diff --git a/syft/pkg/cataloger/lua/testdata/rockspec/build-first-1.0-1.rockspec b/syft/pkg/cataloger/lua/testdata/rockspec/build-first-1.0-1.rockspec new file mode 100644 index 000000000..94b3f4490 --- /dev/null +++ b/syft/pkg/cataloger/lua/testdata/rockspec/build-first-1.0-1.rockspec @@ -0,0 +1,19 @@ +build = { + type = "builtin", + modules = { + foo = "src/foo.lua" + } +} +package = "foo" +version = "1.0-1" +source = { + url = "git+https://github.com/example/foo.git" +} +description = { + summary = "an example rock", + homepage = "https://github.com/example/foo", + license = "MIT" +} +dependencies = { + "lua >= 5.1" +} diff --git a/syft/pkg/cataloger/lua/testdata/rockspec/empty.rockspec b/syft/pkg/cataloger/lua/testdata/rockspec/empty.rockspec new file mode 100644 index 000000000..e69de29bb diff --git a/syft/pkg/cataloger/lua/testdata/rockspec/whitespace-only.rockspec b/syft/pkg/cataloger/lua/testdata/rockspec/whitespace-only.rockspec new file mode 100644 index 000000000..925bd69ca --- /dev/null +++ b/syft/pkg/cataloger/lua/testdata/rockspec/whitespace-only.rockspec @@ -0,0 +1,2 @@ + +