diff --git a/analyzer/analyzer.go b/analyzer/analyzer.go index 186b25b43..8b4c7163f 100644 --- a/analyzer/analyzer.go +++ b/analyzer/analyzer.go @@ -185,28 +185,23 @@ func (a Analyzer) ImageConfigAnalyzerVersions() map[string]int { } func (a Analyzer) AnalyzeFile(ctx context.Context, wg *sync.WaitGroup, limit *semaphore.Weighted, result *AnalysisResult, - dir, filePath string, info os.FileInfo, opener Opener) (err error) { + dir, filePath string, info os.FileInfo, opener Opener) (cleaner func() error, err error) { if info.IsDir() { - return nil + return nil, nil } for _, d := range a.drivers { // filepath extracted from tar file doesn't have the prefix "/" if !d.Required(strings.TrimLeft(filePath, "/"), info) { continue } - rc, cleaner, err := opener() + rc, c, err := opener() if err != nil { - return xerrors.Errorf("unable to open a file (%s): %w", filePath, err) + return nil, xerrors.Errorf("unable to open a file (%s): %w", filePath, err) } - defer func() { - err := cleaner() - if err != nil { - log.Logger.Warn("Clean temp directory error: %s", err) - } - }() + cleaner = c if err = limit.Acquire(ctx, 1); err != nil { - return xerrors.Errorf("semaphore acquire: %w", err) + return nil, xerrors.Errorf("semaphore acquire: %w", err) } wg.Add(1) @@ -223,9 +218,8 @@ func (a Analyzer) AnalyzeFile(ctx context.Context, wg *sync.WaitGroup, limit *se result.Merge(ret) }(d, AnalysisTarget{Dir: dir, FilePath: filePath, ContentReader: rc}) } - wg.Wait() - return nil + return cleaner, nil } func (a Analyzer) AnalyzeImageConfig(targetOS types.OS, configBlob []byte) []types.Package { diff --git a/artifact/image/image.go b/artifact/image/image.go index 249b71983..e6f57f7ef 100644 --- a/artifact/image/image.go +++ b/artifact/image/image.go @@ -195,23 +195,37 @@ func (a Artifact) inspectLayer(ctx context.Context, diffID string) (types.BlobIn return types.BlobInfo{}, xerrors.Errorf("unable to get uncompressed layer %s: %w", diffID, err) } + var cleaners []func() error var wg sync.WaitGroup result := new(analyzer.AnalysisResult) limit := semaphore.NewWeighted(parallel) opqDirs, whFiles, err := a.walker.Walk(r, func(filePath string, info os.FileInfo, opener analyzer.Opener) error { - if err = a.analyzer.AnalyzeFile(ctx, &wg, limit, result, "", filePath, info, opener); err != nil { + cleaner, err := a.analyzer.AnalyzeFile(ctx, &wg, limit, result, "", filePath, info, opener) + if err != nil { return xerrors.Errorf("failed to analyze %s: %w", filePath, err) } + if cleaner != nil { + cleaners = append(cleaners, cleaner) + } + return nil }) if err != nil { return types.BlobInfo{}, xerrors.Errorf("walk error: %w", err) + } // Wait for all the goroutine to finish. wg.Wait() + // Clean for all temporary data after all analyzers. + for _, c := range cleaners { + if err := c(); err != nil { + log.Logger.Warn("Clean temp directory error: %s", err) + } + } + // Sort the analysis result for consistent results result.Sort() diff --git a/artifact/local/fs.go b/artifact/local/fs.go index dcacc97eb..9db76111a 100644 --- a/artifact/local/fs.go +++ b/artifact/local/fs.go @@ -20,6 +20,7 @@ import ( "github.com/aquasecurity/fanal/cache" "github.com/aquasecurity/fanal/config/scanner" "github.com/aquasecurity/fanal/hook" + "github.com/aquasecurity/fanal/log" "github.com/aquasecurity/fanal/types" "github.com/aquasecurity/fanal/walker" ) @@ -77,6 +78,7 @@ func buildAbsPaths(base string, paths []string) []string { } func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) { + var cleaners []func() error var wg sync.WaitGroup result := new(analyzer.AnalysisResult) limit := semaphore.NewWeighted(parallel) @@ -87,9 +89,14 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) if err != nil { return xerrors.Errorf("filepath rel (%s): %w", filePath, err) } - if err = a.analyzer.AnalyzeFile(ctx, &wg, limit, result, a.dir, filePath, info, opener); err != nil { + cleaner, err := a.analyzer.AnalyzeFile(ctx, &wg, limit, result, a.dir, filePath, info, opener) + if err != nil { return xerrors.Errorf("analyze file (%s): %w", filePath, err) } + if cleaner != nil { + cleaners = append(cleaners, cleaner) + } + return nil }) if err != nil { @@ -99,6 +106,13 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) // Wait for all the goroutine to finish. wg.Wait() + // Clean for all temporary data after all analyzers. + for _, c := range cleaners { + if err := c(); err != nil { + log.Logger.Warn("Clean temp directory error: %s", err) + } + } + // Sort the analysis result for consistent results result.Sort() diff --git a/walker/walk.go b/walker/walk.go index 26b908437..573af2a8c 100644 --- a/walker/walk.go +++ b/walker/walk.go @@ -14,7 +14,7 @@ var ( systemDirs = []string{"proc", "sys", "dev"} ) -const ThresholdSize = int64(200) << 20 +const ThresholdSize = int64(200) << 20 // 200MB type WalkFunc func(filePath string, info os.FileInfo, opener analyzer.Opener) error