Skip to content

Commit 89842bd

Browse files
authored
chore: migrate syft to use mholt/archives instead of anchore fork (#4029)
--------- Signed-off-by: Kudryavcev Nikolay <[email protected]> Signed-off-by: Christopher Phillips <[email protected]> Signed-off-by: Alex Goodman <[email protected]>
1 parent 4a60c41 commit 89842bd

17 files changed

+719
-414
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ syft <image> -o <format>
106106
Where the `formats` available are:
107107
- `syft-json`: Use this to get as much information out of Syft as possible!
108108
- `syft-text`: A row-oriented, human-and-machine-friendly output.
109-
- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/).
110-
- `[email protected]`: A XML report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/).
109+
- `cyclonedx-xml`: An XML report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/).
110+
- `[email protected]`: An XML report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/).
111111
- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/).
112112
- `[email protected]`: A JSON report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/).
113113
- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.3 specification](https://spdx.github.io/spdx-spec/v2.3/).

go.mod

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ require (
1111
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
1212
github.com/acobaugh/osrelease v0.1.0
1313
github.com/adrg/xdg v0.5.3
14-
github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51
1514
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
1615
github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716
1716
github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2
@@ -168,7 +167,6 @@ require (
168167
github.com/goccy/go-yaml v1.18.0
169168
github.com/gogo/protobuf v1.3.2 // indirect
170169
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
171-
github.com/golang/snappy v0.0.4 // indirect
172170
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
173171
github.com/google/s2a-go v0.1.8 // indirect
174172
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
@@ -209,10 +207,6 @@ require (
209207
github.com/muesli/cancelreader v0.2.2 // indirect
210208
github.com/muesli/termenv v0.16.0 // indirect
211209
github.com/ncruces/go-strftime v0.1.9 // indirect
212-
github.com/nwaples/rardecode v1.1.3 // indirect
213-
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
214-
github.com/olekukonko/errors v1.1.0 // indirect
215-
github.com/olekukonko/ll v0.1.2 // indirect
216210
github.com/opencontainers/image-spec v1.1.1 // indirect
217211
github.com/opencontainers/runtime-spec v1.1.0 // indirect
218212
github.com/opencontainers/selinux v1.13.0 // indirect
@@ -319,7 +313,10 @@ require (
319313
github.com/json-iterator/go v1.1.12 // indirect
320314
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
321315
github.com/modern-go/reflect2 v1.0.2 // indirect
316+
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
322317
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
318+
github.com/olekukonko/errors v1.1.0 // indirect
319+
github.com/olekukonko/ll v0.1.2 // indirect
323320
github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect
324321
gonum.org/v1/gonum v0.15.1 // indirect
325322
)

go.sum

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
110110
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
111111
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
112112
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
113-
github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51 h1:yhk+P8lF3ZiROjmaVRao9WGTRo4b/wYjoKEiAHWrKwc=
114-
github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51/go.mod h1:nwuGSd7aZp0rtYt79YggCGafz1RYsclE7pi3fhLwvuw=
115113
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4axJaGBvXHU0VCCzLN5Wf5XbKStU=
116114
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw=
117115
github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716 h1:2sIdYJlQESEnyk3Y0WD2vXWW5eD2iMz9Ev8fj1Z8LNA=
@@ -479,8 +477,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
479477
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
480478
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
481479
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
482-
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
483-
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
484480
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
485481
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
486482
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -755,8 +751,6 @@ github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 h1:kpt9ZfKcm+
755751
github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1/go.mod h1:qgCw4bBKZX8qMgGeEZzGFVT3notl42dBjNqO2jut0M0=
756752
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE=
757753
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8=
758-
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
759-
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
760754
github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A=
761755
github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
762756
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc=

internal/file/tar_file_traversal.go

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,48 @@
11
package file
22

33
import (
4+
"context"
45
"fmt"
56
"os"
67
"path/filepath"
78

89
"github.com/bmatcuk/doublestar/v4"
10+
"github.com/mholt/archives"
911

10-
"github.com/anchore/archiver/v3"
12+
"github.com/anchore/syft/internal"
1113
)
1214

15+
// TraverseFilesInTar enumerates all paths stored within a tar archive using the visitor pattern.
16+
func TraverseFilesInTar(ctx context.Context, archivePath string, visitor archives.FileHandler) error {
17+
tarReader, err := os.Open(archivePath)
18+
if err != nil {
19+
return fmt.Errorf("unable to open tar archive (%s): %w", archivePath, err)
20+
}
21+
defer internal.CloseAndLogError(tarReader, archivePath)
22+
23+
format, _, err := archives.Identify(ctx, archivePath, nil)
24+
if err != nil {
25+
return fmt.Errorf("failed to identify tar compression format: %w", err)
26+
}
27+
28+
extractor, ok := format.(archives.Extractor)
29+
if !ok {
30+
return fmt.Errorf("file format does not support extraction: %s", archivePath)
31+
}
32+
33+
return extractor.Extract(ctx, tarReader, visitor)
34+
}
35+
1336
// ExtractGlobsFromTarToUniqueTempFile extracts paths matching the given globs within the given archive to a temporary directory, returning file openers for each file extracted.
14-
func ExtractGlobsFromTarToUniqueTempFile(archivePath, dir string, globs ...string) (map[string]Opener, error) {
37+
func ExtractGlobsFromTarToUniqueTempFile(ctx context.Context, archivePath, dir string, globs ...string) (map[string]Opener, error) {
1538
results := make(map[string]Opener)
1639

1740
// don't allow for full traversal, only select traversal from given paths
1841
if len(globs) == 0 {
1942
return results, nil
2043
}
2144

22-
visitor := func(file archiver.File) error {
23-
defer file.Close()
24-
45+
visitor := func(_ context.Context, file archives.FileInfo) error {
2546
// ignore directories
2647
if file.IsDir() {
2748
return nil
@@ -43,7 +64,13 @@ func ExtractGlobsFromTarToUniqueTempFile(archivePath, dir string, globs ...strin
4364
// provides a ReadCloser. It is up to the caller to handle closing the file explicitly.
4465
defer tempFile.Close()
4566

46-
if err := safeCopy(tempFile, file.ReadCloser); err != nil {
67+
packedFile, err := file.Open()
68+
if err != nil {
69+
return fmt.Errorf("unable to read file=%q from tar=%q: %w", file.NameInArchive, archivePath, err)
70+
}
71+
defer internal.CloseAndLogError(packedFile, archivePath)
72+
73+
if err := safeCopy(tempFile, packedFile); err != nil {
4774
return fmt.Errorf("unable to copy source=%q for tar=%q: %w", file.Name(), archivePath, err)
4875
}
4976

@@ -52,7 +79,7 @@ func ExtractGlobsFromTarToUniqueTempFile(archivePath, dir string, globs ...strin
5279
return nil
5380
}
5481

55-
return results, archiver.Walk(archivePath, visitor)
82+
return results, TraverseFilesInTar(ctx, archivePath, visitor)
5683
}
5784

5885
func matchesAnyGlob(name string, globs ...string) bool {

internal/file/zip_file_manifest.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package file
22

33
import (
4+
"context"
45
"os"
56
"sort"
67
"strings"
78

9+
"github.com/mholt/archives"
810
"github.com/scylladb/go-set/strset"
911

1012
"github.com/anchore/syft/internal/log"
@@ -14,22 +16,25 @@ import (
1416
type ZipFileManifest map[string]os.FileInfo
1517

1618
// NewZipFileManifest creates and returns a new ZipFileManifest populated with path and metadata from the given zip archive path.
17-
func NewZipFileManifest(archivePath string) (ZipFileManifest, error) {
18-
zipReader, err := OpenZip(archivePath)
19+
func NewZipFileManifest(ctx context.Context, archivePath string) (ZipFileManifest, error) {
20+
zipReader, err := os.Open(archivePath)
1921
manifest := make(ZipFileManifest)
2022
if err != nil {
2123
log.Debugf("unable to open zip archive (%s): %v", archivePath, err)
2224
return manifest, err
2325
}
2426
defer func() {
25-
err = zipReader.Close()
26-
if err != nil {
27+
if err = zipReader.Close(); err != nil {
2728
log.Debugf("unable to close zip archive (%s): %+v", archivePath, err)
2829
}
2930
}()
3031

31-
for _, file := range zipReader.File {
32-
manifest.Add(file.Name, file.FileInfo())
32+
err = archives.Zip{}.Extract(ctx, zipReader, func(_ context.Context, file archives.FileInfo) error {
33+
manifest.Add(file.NameInArchive, file.FileInfo)
34+
return nil
35+
})
36+
if err != nil {
37+
return manifest, err
3338
}
3439
return manifest, nil
3540
}

internal/file/zip_file_manifest_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package file
55

66
import (
7+
"context"
78
"encoding/json"
89
"os"
910
"path"
@@ -24,7 +25,7 @@ func TestNewZipFileManifest(t *testing.T) {
2425

2526
archiveFilePath := setupZipFileTest(t, sourceDirPath, false)
2627

27-
actual, err := NewZipFileManifest(archiveFilePath)
28+
actual, err := NewZipFileManifest(context.Background(), archiveFilePath)
2829
if err != nil {
2930
t.Fatalf("unable to extract from unzip archive: %+v", err)
3031
}
@@ -59,7 +60,7 @@ func TestNewZip64FileManifest(t *testing.T) {
5960
sourceDirPath := path.Join(cwd, "test-fixtures", "zip-source")
6061
archiveFilePath := setupZipFileTest(t, sourceDirPath, true)
6162

62-
actual, err := NewZipFileManifest(archiveFilePath)
63+
actual, err := NewZipFileManifest(context.Background(), archiveFilePath)
6364
if err != nil {
6465
t.Fatalf("unable to extract from unzip archive: %+v", err)
6566
}
@@ -99,7 +100,7 @@ func TestZipFileManifest_GlobMatch(t *testing.T) {
99100

100101
archiveFilePath := setupZipFileTest(t, sourceDirPath, false)
101102

102-
z, err := NewZipFileManifest(archiveFilePath)
103+
z, err := NewZipFileManifest(context.Background(), archiveFilePath)
103104
if err != nil {
104105
t.Fatalf("unable to extract from unzip archive: %+v", err)
105106
}

0 commit comments

Comments
 (0)