mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 00:43:20 +01:00
fix: handle individual cataloger panics (#1636)
This commit is contained in:
parent
8e1205f7ab
commit
24584a4d27
@ -46,14 +46,11 @@ func generateCatalogPackagesTask(app *config.Application) (Task, error) {
|
|||||||
|
|
||||||
task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
|
task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
|
||||||
packageCatalog, relationships, theDistro, err := syft.CatalogPackages(src, app.ToCatalogerConfig())
|
packageCatalog, relationships, theDistro, err := syft.CatalogPackages(src, app.ToCatalogerConfig())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
results.PackageCatalog = packageCatalog
|
results.PackageCatalog = packageCatalog
|
||||||
results.LinuxDistribution = theDistro
|
results.LinuxDistribution = theDistro
|
||||||
|
|
||||||
return relationships, nil
|
return relationships, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return task, nil
|
return task, nil
|
||||||
|
|||||||
@ -70,13 +70,10 @@ func CatalogPackages(src *source.Source, cfg cataloger.Config) (*pkg.Catalog, []
|
|||||||
}
|
}
|
||||||
|
|
||||||
catalog, relationships, err := cataloger.Catalog(resolver, release, cfg.Parallelism, catalogers...)
|
catalog, relationships, err := cataloger.Catalog(resolver, release, cfg.Parallelism, catalogers...)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
relationships = append(relationships, newSourceRelationshipsFromCatalog(src, catalog)...)
|
relationships = append(relationships, newSourceRelationshipsFromCatalog(src, catalog)...)
|
||||||
|
|
||||||
return catalog, relationships, release, nil
|
return catalog, relationships, release, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSourceRelationshipsFromCatalog(src *source.Source, c *pkg.Catalog) []artifact.Relationship {
|
func newSourceRelationshipsFromCatalog(src *source.Source, c *pkg.Catalog) []artifact.Relationship {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package cataloger
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
@ -49,8 +50,15 @@ func newMonitor() (*progress.Manual, *progress.Manual) {
|
|||||||
return &filesProcessed, &packagesDiscovered
|
return &filesProcessed, &packagesDiscovered
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCataloger(cataloger pkg.Cataloger, resolver source.FileResolver) (*catalogResult, error) {
|
func runCataloger(cataloger pkg.Cataloger, resolver source.FileResolver) (catalogerResult *catalogResult, err error) {
|
||||||
catalogerResult := new(catalogResult)
|
// handle individual cataloger panics
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
err = fmt.Errorf("%v at:\n%s", e, string(debug.Stack()))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
catalogerResult = new(catalogResult)
|
||||||
|
|
||||||
// find packages from the underlying raw data
|
// find packages from the underlying raw data
|
||||||
log.WithFields("cataloger", cataloger.Name()).Trace("cataloging started")
|
log.WithFields("cataloger", cataloger.Name()).Trace("cataloging started")
|
||||||
@ -88,7 +96,7 @@ func runCataloger(cataloger pkg.Cataloger, resolver source.FileResolver) (*catal
|
|||||||
}
|
}
|
||||||
catalogerResult.Relationships = append(catalogerResult.Relationships, relationships...)
|
catalogerResult.Relationships = append(catalogerResult.Relationships, relationships...)
|
||||||
log.WithFields("cataloger", cataloger.Name()).Trace("cataloging complete")
|
log.WithFields("cataloger", cataloger.Name()).Trace("cataloging complete")
|
||||||
return catalogerResult, nil
|
return catalogerResult, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog a given source (container image or filesystem) with the given catalogers, returning all discovered packages.
|
// Catalog a given source (container image or filesystem) with the given catalogers, returning all discovered packages.
|
||||||
@ -100,7 +108,11 @@ func runCataloger(cataloger pkg.Cataloger, resolver source.FileResolver) (*catal
|
|||||||
func Catalog(resolver source.FileResolver, release *linux.Release, parallelism int, catalogers ...pkg.Cataloger) (*pkg.Catalog, []artifact.Relationship, error) {
|
func Catalog(resolver source.FileResolver, release *linux.Release, parallelism int, catalogers ...pkg.Cataloger) (*pkg.Catalog, []artifact.Relationship, error) {
|
||||||
catalog := pkg.NewCatalog()
|
catalog := pkg.NewCatalog()
|
||||||
var allRelationships []artifact.Relationship
|
var allRelationships []artifact.Relationship
|
||||||
|
|
||||||
filesProcessed, packagesDiscovered := newMonitor()
|
filesProcessed, packagesDiscovered := newMonitor()
|
||||||
|
defer filesProcessed.SetCompleted()
|
||||||
|
defer packagesDiscovered.SetCompleted()
|
||||||
|
|
||||||
// perform analysis, accumulating errors for each failed analysis
|
// perform analysis, accumulating errors for each failed analysis
|
||||||
var errs error
|
var errs error
|
||||||
|
|
||||||
@ -158,7 +170,6 @@ func Catalog(resolver source.FileResolver, release *linux.Release, parallelism i
|
|||||||
for result := range results {
|
for result := range results {
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
errs = multierror.Append(errs, result.Error)
|
errs = multierror.Append(errs, result.Error)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
for _, p := range result.Packages {
|
for _, p := range result.Packages {
|
||||||
catalog.Add(p)
|
catalog.Add(p)
|
||||||
@ -168,14 +179,7 @@ func Catalog(resolver source.FileResolver, release *linux.Release, parallelism i
|
|||||||
|
|
||||||
allRelationships = append(allRelationships, pkg.NewRelationships(catalog)...)
|
allRelationships = append(allRelationships, pkg.NewRelationships(catalog)...)
|
||||||
|
|
||||||
if errs != nil {
|
return catalog, allRelationships, errs
|
||||||
return nil, nil, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
filesProcessed.SetCompleted()
|
|
||||||
packagesDiscovered.SetCompleted()
|
|
||||||
|
|
||||||
return catalog, allRelationships, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func packageFileOwnershipRelationships(p pkg.Package, resolver source.FilePathResolver) ([]artifact.Relationship, error) {
|
func packageFileOwnershipRelationships(p pkg.Package, resolver source.FilePathResolver) ([]artifact.Relationship, error) {
|
||||||
|
|||||||
67
syft/pkg/cataloger/catalog_test.go
Normal file
67
syft/pkg/cataloger/catalog_test.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package cataloger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/linux"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_CatalogPanicHandling(t *testing.T) {
|
||||||
|
catalog, relationships, err := Catalog(
|
||||||
|
source.NewMockResolverForPaths(),
|
||||||
|
&linux.Release{},
|
||||||
|
1,
|
||||||
|
panickingCataloger{},
|
||||||
|
returningCataloger{},
|
||||||
|
)
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "catalog_test.go")
|
||||||
|
require.Len(t, catalog.Sorted(), 2)
|
||||||
|
require.Len(t, relationships, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
type panickingCataloger struct{}
|
||||||
|
|
||||||
|
func (p panickingCataloger) Name() string {
|
||||||
|
return "panicking-cataloger"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p panickingCataloger) Catalog(_ source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
panic("something bad happened")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ pkg.Cataloger = (*panickingCataloger)(nil)
|
||||||
|
|
||||||
|
type returningCataloger struct{}
|
||||||
|
|
||||||
|
func (p returningCataloger) Name() string {
|
||||||
|
return "returning-cataloger"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p returningCataloger) Catalog(_ source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
pkg1 := pkg.Package{
|
||||||
|
Name: "package-1",
|
||||||
|
Version: "1.0",
|
||||||
|
}
|
||||||
|
pkg1.SetID()
|
||||||
|
pkg2 := pkg.Package{
|
||||||
|
Name: "package-2",
|
||||||
|
Version: "2.0",
|
||||||
|
}
|
||||||
|
pkg2.SetID()
|
||||||
|
return []pkg.Package{pkg1, pkg2}, []artifact.Relationship{
|
||||||
|
{
|
||||||
|
From: pkg1,
|
||||||
|
To: pkg2,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ pkg.Cataloger = (*returningCataloger)(nil)
|
||||||
Loading…
x
Reference in New Issue
Block a user