From 8a9a418708e705804eb89b5a90c2a9708a438a71 Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Fri, 17 Sep 2021 00:57:48 +0900 Subject: [PATCH 1/8] feat(arch): add archlinux --- analyzer/const.go | 1 + analyzer/os/archlinux/archlinux.go | 55 +++++++++++++++++++ analyzer/os/archlinux/archlinux_test.go | 53 ++++++++++++++++++ .../archlinux/testdata/archlinux/os-release | 10 ++++ .../testdata/not_archlinux/os-release | 1 + analyzer/os/const.go | 3 + 6 files changed, 123 insertions(+) create mode 100644 analyzer/os/archlinux/archlinux.go create mode 100644 analyzer/os/archlinux/archlinux_test.go create mode 100644 analyzer/os/archlinux/testdata/archlinux/os-release create mode 100644 analyzer/os/archlinux/testdata/not_archlinux/os-release diff --git a/analyzer/const.go b/analyzer/const.go index 3d1bcdb67..db65dfe7a 100644 --- a/analyzer/const.go +++ b/analyzer/const.go @@ -8,6 +8,7 @@ const ( // ====== TypeAlpine Type = "alpine" TypeAmazon Type = "amazon" + TypeArch Type = "arch" TypeCBLMariner Type = "cbl-mariner" TypeDebian Type = "debian" TypePhoton Type = "photon" diff --git a/analyzer/os/archlinux/archlinux.go b/analyzer/os/archlinux/archlinux.go new file mode 100644 index 000000000..65bab6f76 --- /dev/null +++ b/analyzer/os/archlinux/archlinux.go @@ -0,0 +1,55 @@ +package archlinux + +import ( + "bufio" + "bytes" + "os" + "strings" + + "github.com/aquasecurity/fanal/analyzer" + aos "github.com/aquasecurity/fanal/analyzer/os" + "github.com/aquasecurity/fanal/types" + "github.com/aquasecurity/fanal/utils" + "golang.org/x/xerrors" +) + +func init() { + analyzer.RegisterAnalyzer(&archlinuxOSAnalyzer{}) +} + +const version = 1 + +var requiredFiles = []string{ + "usr/lib/os-release", + "etc/os-release", +} + +type archlinuxOSAnalyzer struct{} + +func (a archlinuxOSAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.AnalysisResult, error) { + scanner := bufio.NewScanner(bytes.NewBuffer(target.Content)) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "NAME=\"Arch Linux") { + return &analyzer.AnalysisResult{ + OS: &types.OS{ + Family: aos.Arch, + Name: "Arch Linux", + }, + }, nil + } + } + return nil, xerrors.Errorf("arch: %w", aos.AnalyzeOSError) +} + +func (a archlinuxOSAnalyzer) Required(filePath string, _ os.FileInfo) bool { + return utils.StringInSlice(filePath, requiredFiles) +} + +func (a archlinuxOSAnalyzer) Type() analyzer.Type { + return analyzer.TypeArch +} + +func (a archlinuxOSAnalyzer) Version() int { + return version +} diff --git a/analyzer/os/archlinux/archlinux_test.go b/analyzer/os/archlinux/archlinux_test.go new file mode 100644 index 000000000..77ac7fb9e --- /dev/null +++ b/analyzer/os/archlinux/archlinux_test.go @@ -0,0 +1,53 @@ +package archlinux + +import ( + "os" + "testing" + + "github.com/aquasecurity/fanal/analyzer" + aos "github.com/aquasecurity/fanal/analyzer/os" + "github.com/aquasecurity/fanal/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_archlinuxOSAnalyzer_Analyze(t *testing.T) { + tests := []struct { + name string + inputFile string + want *analyzer.AnalysisResult + wantErr string + }{ + { + name: "happy path with ArchLinux", + inputFile: "testdata/archlinux/os-release", + want: &analyzer.AnalysisResult{ + OS: &types.OS{Family: aos.Arch, Name: "Arch Linux"}, + }, + }, + { + name: "sad path", + inputFile: "testdata/not_archlinux/os-release", + wantErr: "arch: unable to analyze OS information", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := archlinuxOSAnalyzer{} + b, err := os.ReadFile(tt.inputFile) + require.NoError(t, err) + + got, err := a.Analyze(analyzer.AnalysisTarget{ + FilePath: "etc/os-release", + Content: b, + }) + if tt.wantErr != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErr) + return + } + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/analyzer/os/archlinux/testdata/archlinux/os-release b/analyzer/os/archlinux/testdata/archlinux/os-release new file mode 100644 index 000000000..1ebbef58a --- /dev/null +++ b/analyzer/os/archlinux/testdata/archlinux/os-release @@ -0,0 +1,10 @@ +NAME="Arch Linux" +PRETTY_NAME="Arch Linux" +ID=arch +BUILD_ID=rolling +ANSI_COLOR="38;2;23;147;209" +HOME_URL="https://archlinux.org/" +DOCUMENTATION_URL="https://wiki.archlinux.org/" +SUPPORT_URL="https://bbs.archlinux.org/" +BUG_REPORT_URL="https://bugs.archlinux.org/" +LOGO=archlinux \ No newline at end of file diff --git a/analyzer/os/archlinux/testdata/not_archlinux/os-release b/analyzer/os/archlinux/testdata/not_archlinux/os-release new file mode 100644 index 000000000..574c7bd1e --- /dev/null +++ b/analyzer/os/archlinux/testdata/not_archlinux/os-release @@ -0,0 +1 @@ +Red Hat Linux release 6.2 (Zoot) diff --git a/analyzer/os/const.go b/analyzer/os/const.go index d1c0813b0..82d5a5654 100644 --- a/analyzer/os/const.go +++ b/analyzer/os/const.go @@ -57,6 +57,9 @@ const ( // Alpine is done Alpine = "alpine" + + // Arch is done + Arch = "arch" ) var AnalyzeOSError = xerrors.New("unable to analyze OS information") From 1b7d3288ba54ed7c70fe4f7c0c50f5add8db934a Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Fri, 17 Sep 2021 01:00:50 +0900 Subject: [PATCH 2/8] feat(arch): add import --- analyzer/all/import.go | 1 + 1 file changed, 1 insertion(+) diff --git a/analyzer/all/import.go b/analyzer/all/import.go index 5f9203ae3..2b17bbca3 100644 --- a/analyzer/all/import.go +++ b/analyzer/all/import.go @@ -21,6 +21,7 @@ import ( _ "github.com/aquasecurity/fanal/analyzer/language/rust/cargo" _ "github.com/aquasecurity/fanal/analyzer/os/alpine" _ "github.com/aquasecurity/fanal/analyzer/os/amazonlinux" + _ "github.com/aquasecurity/fanal/analyzer/os/archlinux" _ "github.com/aquasecurity/fanal/analyzer/os/debian" _ "github.com/aquasecurity/fanal/analyzer/os/mariner" _ "github.com/aquasecurity/fanal/analyzer/os/photon" From 8b9e1be8d218bfa78f4f2c01d38bfee7d4af7bc0 Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Fri, 17 Sep 2021 04:30:54 +0900 Subject: [PATCH 3/8] feat(pkg/pacman): add pacman --- analyzer/all/import.go | 1 + analyzer/const.go | 7 +- analyzer/pkg/pacman/pacman.go | 128 +++++++++ analyzer/pkg/pacman/pacman_test.go | 220 +++++++++++++++ .../pkg/pacman/testdata/bash-5.1.008-1/desc | 51 ++++ .../pkg/pacman/testdata/bash-5.1.008-1/files | 259 ++++++++++++++++++ .../pkg/pacman/testdata/bash-5.1.008-1/mtree | Bin 0 -> 11984 bytes 7 files changed, 663 insertions(+), 3 deletions(-) create mode 100644 analyzer/pkg/pacman/pacman.go create mode 100644 analyzer/pkg/pacman/pacman_test.go create mode 100644 analyzer/pkg/pacman/testdata/bash-5.1.008-1/desc create mode 100644 analyzer/pkg/pacman/testdata/bash-5.1.008-1/files create mode 100644 analyzer/pkg/pacman/testdata/bash-5.1.008-1/mtree diff --git a/analyzer/all/import.go b/analyzer/all/import.go index 2b17bbca3..879c1a233 100644 --- a/analyzer/all/import.go +++ b/analyzer/all/import.go @@ -30,5 +30,6 @@ import ( _ "github.com/aquasecurity/fanal/analyzer/os/ubuntu" _ "github.com/aquasecurity/fanal/analyzer/pkg/apk" _ "github.com/aquasecurity/fanal/analyzer/pkg/dpkg" + _ "github.com/aquasecurity/fanal/analyzer/pkg/pacman" _ "github.com/aquasecurity/fanal/analyzer/pkg/rpm" ) diff --git a/analyzer/const.go b/analyzer/const.go index db65dfe7a..abe379451 100644 --- a/analyzer/const.go +++ b/analyzer/const.go @@ -22,9 +22,10 @@ const ( TypeUbuntu Type = "ubuntu" // OS Package - TypeApk Type = "apk" - TypeDpkg Type = "dpkg" - TypeRpm Type = "rpm" + TypeApk Type = "apk" + TypeDpkg Type = "dpkg" + TypePacman Type = "pacman" + TypeRpm Type = "rpm" // ============================ // Programming Language Package diff --git a/analyzer/pkg/pacman/pacman.go b/analyzer/pkg/pacman/pacman.go new file mode 100644 index 000000000..25cd8990b --- /dev/null +++ b/analyzer/pkg/pacman/pacman.go @@ -0,0 +1,128 @@ +package pacman + +import ( + "bufio" + "bytes" + "os" + "path/filepath" + "strings" + + "github.com/aquasecurity/fanal/analyzer" + "github.com/aquasecurity/fanal/types" + "golang.org/x/xerrors" +) + +func init() { + analyzer.RegisterAnalyzer(&pacmanAnalyzer{}) +} + +const version = 1 + +const installDir = "var/lib/pacman/local/" + +type pacmanAnalyzer struct{} + +func (a pacmanAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.AnalysisResult, error) { + scanner := bufio.NewScanner(bytes.NewBuffer(target.Content)) + dir, fileName := filepath.Split(target.FilePath) + if !strings.HasPrefix(dir, installDir) { + return nil, nil + } + if fileName == "desc" { + pkg, err := a.parsePacmanPkgDesc(scanner) + if err != nil { + return nil, xerrors.Errorf("failed to parse desc: %w", err) + } + return &analyzer.AnalysisResult{ + PackageInfos: []types.PackageInfo{ + {FilePath: target.FilePath, Packages: []types.Package{pkg}}, + }, + }, nil + } + if fileName == "files" { + result, err := a.parsePacmanPkgFiles(scanner) + if err != nil { + return nil, xerrors.Errorf("failed to parse files: %w", err) + } + return result, nil + } + return nil, nil +} + +func (a pacmanAnalyzer) parsePacmanPkgDesc(scanner *bufio.Scanner) (types.Package, error) { + var pkg types.Package + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "%NAME%") { + if scanner.Scan() { + pkg.Name = scanner.Text() + } + } else if strings.HasPrefix(line, "%VERSION%") { + if scanner.Scan() { + version := scanner.Text() + pkg.Version = version + pkg.SrcVersion = version + } + } else if strings.HasPrefix(line, "%BASE%") { + if scanner.Scan() { + pkg.SrcName = scanner.Text() + } + } else if strings.HasPrefix(line, "%ARCH%") { + if scanner.Scan() { + pkg.Arch = scanner.Text() + } + } else if strings.HasPrefix(line, "%LICENSE%") { + if scanner.Scan() { + pkg.License = scanner.Text() + } + } + } + + if err := scanner.Err(); err != nil { + return types.Package{}, xerrors.Errorf("scan error: %w", err) + } + + return pkg, nil +} + +// parsePacmanPkgFiles parses /var/lib/pacman/local/*/files +func (a pacmanAnalyzer) parsePacmanPkgFiles(scanner *bufio.Scanner) (*analyzer.AnalysisResult, error) { + var installedFiles []string + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "%FILES%") { + continue + } + if strings.HasPrefix(line, "%BACKUP%") { + break + } + + if _, fileName := filepath.Split(line); fileName != "" { + installedFiles = append(installedFiles, line) + } + } + + if err := scanner.Err(); err != nil { + return nil, xerrors.Errorf("scan error: %w", err) + } + + return &analyzer.AnalysisResult{ + SystemInstalledFiles: installedFiles, + }, nil +} + +func (a pacmanAnalyzer) Required(filePath string, _ os.FileInfo) bool { + dir, fileName := filepath.Split(filePath) + if !strings.HasPrefix(dir, installDir) { + return false + } + return fileName == "desc" || fileName == "files" +} + +func (a pacmanAnalyzer) Type() analyzer.Type { + return analyzer.TypePacman +} + +func (a pacmanAnalyzer) Version() int { + return version +} diff --git a/analyzer/pkg/pacman/pacman_test.go b/analyzer/pkg/pacman/pacman_test.go new file mode 100644 index 000000000..908bc8224 --- /dev/null +++ b/analyzer/pkg/pacman/pacman_test.go @@ -0,0 +1,220 @@ +package pacman + +import ( + "os" + "testing" + + "github.com/aquasecurity/fanal/analyzer" + "github.com/aquasecurity/fanal/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_pacmanAnalyzer_Analyze(t *testing.T) { + tests := []struct { + name string + testFile string + filepath string + want *analyzer.AnalysisResult + }{ + { + name: "valid desc", + testFile: "./testdata/bash-5.1.008-1/desc", + filepath: "var/lib/pacman/local/bash-5.1.008-1/desc", + want: &analyzer.AnalysisResult{ + PackageInfos: []types.PackageInfo{ + { + FilePath: "var/lib/pacman/local/bash-5.1.008-1/desc", + Packages: []types.Package{ + {Name: "bash", Version: "5.1.008-1", SrcName: "bash", SrcVersion: "5.1.008-1", Arch: "x86_64", License: "GPL"}, + }, + }, + }, + }, + }, + { + name: "valid files", + testFile: "./testdata/bash-5.1.008-1/files", + filepath: "var/lib/pacman/local/bash-5.1.008-1/files", + want: &analyzer.AnalysisResult{ + SystemInstalledFiles: []string{ + "etc/bash.bash_logout", + "etc/bash.bashrc", + "etc/skel/.bash_logout", + "etc/skel/.bash_profile", + "etc/skel/.bashrc", + "usr/bin/bash", + "usr/bin/bashbug", + "usr/bin/sh", + "usr/include/bash/alias.h", + "usr/include/bash/array.h", + "usr/include/bash/arrayfunc.h", + "usr/include/bash/assoc.h", + "usr/include/bash/bashansi.h", + "usr/include/bash/bashintl.h", + "usr/include/bash/bashjmp.h", + "usr/include/bash/bashtypes.h", + "usr/include/bash/builtins.h", + "usr/include/bash/builtins/bashgetopt.h", + "usr/include/bash/builtins/builtext.h", + "usr/include/bash/builtins/common.h", + "usr/include/bash/builtins/getopt.h", + "usr/include/bash/command.h", + "usr/include/bash/config-bot.h", + "usr/include/bash/config-top.h", + "usr/include/bash/config.h", + "usr/include/bash/conftypes.h", + "usr/include/bash/dispose_cmd.h", + "usr/include/bash/error.h", + "usr/include/bash/externs.h", + "usr/include/bash/general.h", + "usr/include/bash/hashlib.h", + "usr/include/bash/include/ansi_stdlib.h", + "usr/include/bash/include/chartypes.h", + "usr/include/bash/include/filecntl.h", + "usr/include/bash/include/gettext.h", + "usr/include/bash/include/maxpath.h", + "usr/include/bash/include/memalloc.h", + "usr/include/bash/include/ocache.h", + "usr/include/bash/include/posixdir.h", + "usr/include/bash/include/posixjmp.h", + "usr/include/bash/include/posixstat.h", + "usr/include/bash/include/posixtime.h", + "usr/include/bash/include/posixwait.h", + "usr/include/bash/include/shmbchar.h", + "usr/include/bash/include/shmbutil.h", + "usr/include/bash/include/shtty.h", + "usr/include/bash/include/stat-time.h", + "usr/include/bash/include/stdc.h", + "usr/include/bash/include/systimes.h", + "usr/include/bash/include/typemax.h", + "usr/include/bash/include/unionwait.h", + "usr/include/bash/jobs.h", + "usr/include/bash/make_cmd.h", + "usr/include/bash/pathnames.h", + "usr/include/bash/quit.h", + "usr/include/bash/shell.h", + "usr/include/bash/sig.h", + "usr/include/bash/siglist.h", + "usr/include/bash/signames.h", + "usr/include/bash/subst.h", + "usr/include/bash/syntax.h", + "usr/include/bash/unwind_prot.h", + "usr/include/bash/variables.h", + "usr/include/bash/version.h", + "usr/include/bash/xmalloc.h", + "usr/include/bash/y.tab.h", + "usr/lib/bash/Makefile.inc", + "usr/lib/bash/accept", + "usr/lib/bash/basename", + "usr/lib/bash/csv", + "usr/lib/bash/cut", + "usr/lib/bash/dirname", + "usr/lib/bash/fdflags", + "usr/lib/bash/finfo", + "usr/lib/bash/head", + "usr/lib/bash/id", + "usr/lib/bash/ln", + "usr/lib/bash/loadables.h", + "usr/lib/bash/logname", + "usr/lib/bash/mkdir", + "usr/lib/bash/mkfifo", + "usr/lib/bash/mktemp", + "usr/lib/bash/mypid", + "usr/lib/bash/pathchk", + "usr/lib/bash/print", + "usr/lib/bash/printenv", + "usr/lib/bash/push", + "usr/lib/bash/realpath", + "usr/lib/bash/rm", + "usr/lib/bash/rmdir", + "usr/lib/bash/seq", + "usr/lib/bash/setpgid", + "usr/lib/bash/sleep", + "usr/lib/bash/strftime", + "usr/lib/bash/sync", + "usr/lib/bash/tee", + "usr/lib/bash/truefalse", + "usr/lib/bash/tty", + "usr/lib/bash/uname", + "usr/lib/bash/unlink", + "usr/lib/bash/whoami", + "usr/lib/pkgconfig/bash.pc", + "usr/share/doc/bash/CHANGES", + "usr/share/doc/bash/COMPAT", + "usr/share/doc/bash/FAQ", + "usr/share/doc/bash/INTRO", + "usr/share/doc/bash/NEWS", + "usr/share/doc/bash/POSIX", + "usr/share/doc/bash/RBASH", + "usr/share/doc/bash/README", + "usr/share/doc/bash/bash.html", + "usr/share/doc/bash/bashref.html", + "usr/share/info/bash.info.gz", + "usr/share/locale/af/LC_MESSAGES/bash.mo", + "usr/share/locale/bg/LC_MESSAGES/bash.mo", + "usr/share/locale/ca/LC_MESSAGES/bash.mo", + "usr/share/locale/cs/LC_MESSAGES/bash.mo", + "usr/share/locale/da/LC_MESSAGES/bash.mo", + "usr/share/locale/de/LC_MESSAGES/bash.mo", + "usr/share/locale/el/LC_MESSAGES/bash.mo", + "usr/share/locale/en@boldquot/LC_MESSAGES/bash.mo", + "usr/share/locale/en@quot/LC_MESSAGES/bash.mo", + "usr/share/locale/eo/LC_MESSAGES/bash.mo", + "usr/share/locale/es/LC_MESSAGES/bash.mo", + "usr/share/locale/et/LC_MESSAGES/bash.mo", + "usr/share/locale/fi/LC_MESSAGES/bash.mo", + "usr/share/locale/fr/LC_MESSAGES/bash.mo", + "usr/share/locale/ga/LC_MESSAGES/bash.mo", + "usr/share/locale/gl/LC_MESSAGES/bash.mo", + "usr/share/locale/hr/LC_MESSAGES/bash.mo", + "usr/share/locale/hu/LC_MESSAGES/bash.mo", + "usr/share/locale/id/LC_MESSAGES/bash.mo", + "usr/share/locale/it/LC_MESSAGES/bash.mo", + "usr/share/locale/ja/LC_MESSAGES/bash.mo", + "usr/share/locale/ko/LC_MESSAGES/bash.mo", + "usr/share/locale/lt/LC_MESSAGES/bash.mo", + "usr/share/locale/nb/LC_MESSAGES/bash.mo", + "usr/share/locale/nl/LC_MESSAGES/bash.mo", + "usr/share/locale/pl/LC_MESSAGES/bash.mo", + "usr/share/locale/pt/LC_MESSAGES/bash.mo", + "usr/share/locale/pt_BR/LC_MESSAGES/bash.mo", + "usr/share/locale/ro/LC_MESSAGES/bash.mo", + "usr/share/locale/ru/LC_MESSAGES/bash.mo", + "usr/share/locale/sk/LC_MESSAGES/bash.mo", + "usr/share/locale/sl/LC_MESSAGES/bash.mo", + "usr/share/locale/sr/LC_MESSAGES/bash.mo", + "usr/share/locale/sv/LC_MESSAGES/bash.mo", + "usr/share/locale/tr/LC_MESSAGES/bash.mo", + "usr/share/locale/uk/LC_MESSAGES/bash.mo", + "usr/share/locale/vi/LC_MESSAGES/bash.mo", + "usr/share/locale/zh_CN/LC_MESSAGES/bash.mo", + "usr/share/locale/zh_TW/LC_MESSAGES/bash.mo", + "usr/share/man/man1/bash.1.gz", + "usr/share/man/man1/bashbug.1.gz", + }, + }, + }, + { + name: "valid mtree", + testFile: "./testdata/bash-5.1.008-1/mtree", + filepath: "var/lib/pacman/local/bash-5.1.008-1/mtree", + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, err := os.ReadFile(tt.testFile) + require.NoError(t, err) + + a := pacmanAnalyzer{} + got, err := a.Analyze(analyzer.AnalysisTarget{ + FilePath: tt.filepath, + Content: b, + }) + require.NoError(t, err) + + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/analyzer/pkg/pacman/testdata/bash-5.1.008-1/desc b/analyzer/pkg/pacman/testdata/bash-5.1.008-1/desc new file mode 100644 index 000000000..14a03c959 --- /dev/null +++ b/analyzer/pkg/pacman/testdata/bash-5.1.008-1/desc @@ -0,0 +1,51 @@ +%NAME% +bash + +%VERSION% +5.1.008-1 + +%BASE% +bash + +%DESC% +The GNU Bourne Again shell + +%URL% +https://www.gnu.org/software/bash/bash.html + +%ARCH% +x86_64 + +%BUILDDATE% +1620554015 + +%INSTALLDATE% +1631696657 + +%PACKAGER% +Levente Polyak + +%SIZE% +8596907 + +%REASON% +1 + +%LICENSE% +GPL + +%VALIDATION% +pgp + +%DEPENDS% +readline +libreadline.so=8-64 +glibc +ncurses + +%OPTDEPENDS% +bash-completion: for tab completion + +%PROVIDES% +sh + diff --git a/analyzer/pkg/pacman/testdata/bash-5.1.008-1/files b/analyzer/pkg/pacman/testdata/bash-5.1.008-1/files new file mode 100644 index 000000000..de6e8f09c --- /dev/null +++ b/analyzer/pkg/pacman/testdata/bash-5.1.008-1/files @@ -0,0 +1,259 @@ +%FILES% +etc/ +etc/bash.bash_logout +etc/bash.bashrc +etc/skel/ +etc/skel/.bash_logout +etc/skel/.bash_profile +etc/skel/.bashrc +usr/ +usr/bin/ +usr/bin/bash +usr/bin/bashbug +usr/bin/sh +usr/include/ +usr/include/bash/ +usr/include/bash/alias.h +usr/include/bash/array.h +usr/include/bash/arrayfunc.h +usr/include/bash/assoc.h +usr/include/bash/bashansi.h +usr/include/bash/bashintl.h +usr/include/bash/bashjmp.h +usr/include/bash/bashtypes.h +usr/include/bash/builtins.h +usr/include/bash/builtins/ +usr/include/bash/builtins/bashgetopt.h +usr/include/bash/builtins/builtext.h +usr/include/bash/builtins/common.h +usr/include/bash/builtins/getopt.h +usr/include/bash/command.h +usr/include/bash/config-bot.h +usr/include/bash/config-top.h +usr/include/bash/config.h +usr/include/bash/conftypes.h +usr/include/bash/dispose_cmd.h +usr/include/bash/error.h +usr/include/bash/externs.h +usr/include/bash/general.h +usr/include/bash/hashlib.h +usr/include/bash/include/ +usr/include/bash/include/ansi_stdlib.h +usr/include/bash/include/chartypes.h +usr/include/bash/include/filecntl.h +usr/include/bash/include/gettext.h +usr/include/bash/include/maxpath.h +usr/include/bash/include/memalloc.h +usr/include/bash/include/ocache.h +usr/include/bash/include/posixdir.h +usr/include/bash/include/posixjmp.h +usr/include/bash/include/posixstat.h +usr/include/bash/include/posixtime.h +usr/include/bash/include/posixwait.h +usr/include/bash/include/shmbchar.h +usr/include/bash/include/shmbutil.h +usr/include/bash/include/shtty.h +usr/include/bash/include/stat-time.h +usr/include/bash/include/stdc.h +usr/include/bash/include/systimes.h +usr/include/bash/include/typemax.h +usr/include/bash/include/unionwait.h +usr/include/bash/jobs.h +usr/include/bash/make_cmd.h +usr/include/bash/pathnames.h +usr/include/bash/quit.h +usr/include/bash/shell.h +usr/include/bash/sig.h +usr/include/bash/siglist.h +usr/include/bash/signames.h +usr/include/bash/subst.h +usr/include/bash/syntax.h +usr/include/bash/unwind_prot.h +usr/include/bash/variables.h +usr/include/bash/version.h +usr/include/bash/xmalloc.h +usr/include/bash/y.tab.h +usr/lib/ +usr/lib/bash/ +usr/lib/bash/Makefile.inc +usr/lib/bash/accept +usr/lib/bash/basename +usr/lib/bash/csv +usr/lib/bash/cut +usr/lib/bash/dirname +usr/lib/bash/fdflags +usr/lib/bash/finfo +usr/lib/bash/head +usr/lib/bash/id +usr/lib/bash/ln +usr/lib/bash/loadables.h +usr/lib/bash/logname +usr/lib/bash/mkdir +usr/lib/bash/mkfifo +usr/lib/bash/mktemp +usr/lib/bash/mypid +usr/lib/bash/pathchk +usr/lib/bash/print +usr/lib/bash/printenv +usr/lib/bash/push +usr/lib/bash/realpath +usr/lib/bash/rm +usr/lib/bash/rmdir +usr/lib/bash/seq +usr/lib/bash/setpgid +usr/lib/bash/sleep +usr/lib/bash/strftime +usr/lib/bash/sync +usr/lib/bash/tee +usr/lib/bash/truefalse +usr/lib/bash/tty +usr/lib/bash/uname +usr/lib/bash/unlink +usr/lib/bash/whoami +usr/lib/pkgconfig/ +usr/lib/pkgconfig/bash.pc +usr/share/ +usr/share/doc/ +usr/share/doc/bash/ +usr/share/doc/bash/CHANGES +usr/share/doc/bash/COMPAT +usr/share/doc/bash/FAQ +usr/share/doc/bash/INTRO +usr/share/doc/bash/NEWS +usr/share/doc/bash/POSIX +usr/share/doc/bash/RBASH +usr/share/doc/bash/README +usr/share/doc/bash/bash.html +usr/share/doc/bash/bashref.html +usr/share/info/ +usr/share/info/bash.info.gz +usr/share/locale/ +usr/share/locale/af/ +usr/share/locale/af/LC_MESSAGES/ +usr/share/locale/af/LC_MESSAGES/bash.mo +usr/share/locale/bg/ +usr/share/locale/bg/LC_MESSAGES/ +usr/share/locale/bg/LC_MESSAGES/bash.mo +usr/share/locale/ca/ +usr/share/locale/ca/LC_MESSAGES/ +usr/share/locale/ca/LC_MESSAGES/bash.mo +usr/share/locale/cs/ +usr/share/locale/cs/LC_MESSAGES/ +usr/share/locale/cs/LC_MESSAGES/bash.mo +usr/share/locale/da/ +usr/share/locale/da/LC_MESSAGES/ +usr/share/locale/da/LC_MESSAGES/bash.mo +usr/share/locale/de/ +usr/share/locale/de/LC_MESSAGES/ +usr/share/locale/de/LC_MESSAGES/bash.mo +usr/share/locale/el/ +usr/share/locale/el/LC_MESSAGES/ +usr/share/locale/el/LC_MESSAGES/bash.mo +usr/share/locale/en@boldquot/ +usr/share/locale/en@boldquot/LC_MESSAGES/ +usr/share/locale/en@boldquot/LC_MESSAGES/bash.mo +usr/share/locale/en@quot/ +usr/share/locale/en@quot/LC_MESSAGES/ +usr/share/locale/en@quot/LC_MESSAGES/bash.mo +usr/share/locale/eo/ +usr/share/locale/eo/LC_MESSAGES/ +usr/share/locale/eo/LC_MESSAGES/bash.mo +usr/share/locale/es/ +usr/share/locale/es/LC_MESSAGES/ +usr/share/locale/es/LC_MESSAGES/bash.mo +usr/share/locale/et/ +usr/share/locale/et/LC_MESSAGES/ +usr/share/locale/et/LC_MESSAGES/bash.mo +usr/share/locale/fi/ +usr/share/locale/fi/LC_MESSAGES/ +usr/share/locale/fi/LC_MESSAGES/bash.mo +usr/share/locale/fr/ +usr/share/locale/fr/LC_MESSAGES/ +usr/share/locale/fr/LC_MESSAGES/bash.mo +usr/share/locale/ga/ +usr/share/locale/ga/LC_MESSAGES/ +usr/share/locale/ga/LC_MESSAGES/bash.mo +usr/share/locale/gl/ +usr/share/locale/gl/LC_MESSAGES/ +usr/share/locale/gl/LC_MESSAGES/bash.mo +usr/share/locale/hr/ +usr/share/locale/hr/LC_MESSAGES/ +usr/share/locale/hr/LC_MESSAGES/bash.mo +usr/share/locale/hu/ +usr/share/locale/hu/LC_MESSAGES/ +usr/share/locale/hu/LC_MESSAGES/bash.mo +usr/share/locale/id/ +usr/share/locale/id/LC_MESSAGES/ +usr/share/locale/id/LC_MESSAGES/bash.mo +usr/share/locale/it/ +usr/share/locale/it/LC_MESSAGES/ +usr/share/locale/it/LC_MESSAGES/bash.mo +usr/share/locale/ja/ +usr/share/locale/ja/LC_MESSAGES/ +usr/share/locale/ja/LC_MESSAGES/bash.mo +usr/share/locale/ko/ +usr/share/locale/ko/LC_MESSAGES/ +usr/share/locale/ko/LC_MESSAGES/bash.mo +usr/share/locale/lt/ +usr/share/locale/lt/LC_MESSAGES/ +usr/share/locale/lt/LC_MESSAGES/bash.mo +usr/share/locale/nb/ +usr/share/locale/nb/LC_MESSAGES/ +usr/share/locale/nb/LC_MESSAGES/bash.mo +usr/share/locale/nl/ +usr/share/locale/nl/LC_MESSAGES/ +usr/share/locale/nl/LC_MESSAGES/bash.mo +usr/share/locale/pl/ +usr/share/locale/pl/LC_MESSAGES/ +usr/share/locale/pl/LC_MESSAGES/bash.mo +usr/share/locale/pt/ +usr/share/locale/pt/LC_MESSAGES/ +usr/share/locale/pt/LC_MESSAGES/bash.mo +usr/share/locale/pt_BR/ +usr/share/locale/pt_BR/LC_MESSAGES/ +usr/share/locale/pt_BR/LC_MESSAGES/bash.mo +usr/share/locale/ro/ +usr/share/locale/ro/LC_MESSAGES/ +usr/share/locale/ro/LC_MESSAGES/bash.mo +usr/share/locale/ru/ +usr/share/locale/ru/LC_MESSAGES/ +usr/share/locale/ru/LC_MESSAGES/bash.mo +usr/share/locale/sk/ +usr/share/locale/sk/LC_MESSAGES/ +usr/share/locale/sk/LC_MESSAGES/bash.mo +usr/share/locale/sl/ +usr/share/locale/sl/LC_MESSAGES/ +usr/share/locale/sl/LC_MESSAGES/bash.mo +usr/share/locale/sr/ +usr/share/locale/sr/LC_MESSAGES/ +usr/share/locale/sr/LC_MESSAGES/bash.mo +usr/share/locale/sv/ +usr/share/locale/sv/LC_MESSAGES/ +usr/share/locale/sv/LC_MESSAGES/bash.mo +usr/share/locale/tr/ +usr/share/locale/tr/LC_MESSAGES/ +usr/share/locale/tr/LC_MESSAGES/bash.mo +usr/share/locale/uk/ +usr/share/locale/uk/LC_MESSAGES/ +usr/share/locale/uk/LC_MESSAGES/bash.mo +usr/share/locale/vi/ +usr/share/locale/vi/LC_MESSAGES/ +usr/share/locale/vi/LC_MESSAGES/bash.mo +usr/share/locale/zh_CN/ +usr/share/locale/zh_CN/LC_MESSAGES/ +usr/share/locale/zh_CN/LC_MESSAGES/bash.mo +usr/share/locale/zh_TW/ +usr/share/locale/zh_TW/LC_MESSAGES/ +usr/share/locale/zh_TW/LC_MESSAGES/bash.mo +usr/share/man/ +usr/share/man/man1/ +usr/share/man/man1/bash.1.gz +usr/share/man/man1/bashbug.1.gz + +%BACKUP% +etc/bash.bashrc d8f3f334e72c0e30032eae1a1229aef1 +etc/bash.bash_logout 472f536d7c9e8250dc4568ec4cfaf294 +etc/skel/.bashrc 027d6bd8f5f6a06b75bb7698cb478089 +etc/skel/.bash_profile 2902e0fee7a9168f3a4fd2ccd60ff047 +etc/skel/.bash_logout 42f4400ed2314bd7519c020d0187edc5 + diff --git a/analyzer/pkg/pacman/testdata/bash-5.1.008-1/mtree b/analyzer/pkg/pacman/testdata/bash-5.1.008-1/mtree new file mode 100644 index 0000000000000000000000000000000000000000..b173e9038ed0902e5aa549f797a6a38e4509d19a GIT binary patch literal 11984 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 literal 0 HcmV?d00001 From f8a0a7bf0bcbeb89db0b7ff658bb50c9af6c123c Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Fri, 17 Sep 2021 04:58:04 +0900 Subject: [PATCH 4/8] feat(pacman): parse version --- analyzer/pkg/pacman/pacman.go | 28 ++++++++++++++++++++++++++-- analyzer/pkg/pacman/pacman_test.go | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/analyzer/pkg/pacman/pacman.go b/analyzer/pkg/pacman/pacman.go index 25cd8990b..7e3d25704 100644 --- a/analyzer/pkg/pacman/pacman.go +++ b/analyzer/pkg/pacman/pacman.go @@ -5,6 +5,7 @@ import ( "bytes" "os" "path/filepath" + "strconv" "strings" "github.com/aquasecurity/fanal/analyzer" @@ -60,8 +61,31 @@ func (a pacmanAnalyzer) parsePacmanPkgDesc(scanner *bufio.Scanner) (types.Packag } else if strings.HasPrefix(line, "%VERSION%") { if scanner.Scan() { version := scanner.Text() - pkg.Version = version - pkg.SrcVersion = version + if strings.Contains(version, ":") { + ss := strings.Split(version, ":") + epoch, err := strconv.Atoi(ss[0]) + if err != nil { + return types.Package{}, xerrors.Errorf("failed to convert epoch: %w", err) + } + ss = strings.Split(ss[1], "-") + version := ss[0] + release := ss[1] + + pkg.Epoch = epoch + pkg.Version = version + pkg.Release = release + pkg.SrcEpoch = epoch + pkg.SrcVersion = version + pkg.SrcRelease = release + } else { + ss := strings.Split(version, "-") + version := ss[0] + release := ss[1] + pkg.Version = version + pkg.Release = release + pkg.SrcVersion = version + pkg.SrcRelease = release + } } } else if strings.HasPrefix(line, "%BASE%") { if scanner.Scan() { diff --git a/analyzer/pkg/pacman/pacman_test.go b/analyzer/pkg/pacman/pacman_test.go index 908bc8224..2c98a4819 100644 --- a/analyzer/pkg/pacman/pacman_test.go +++ b/analyzer/pkg/pacman/pacman_test.go @@ -26,7 +26,7 @@ func Test_pacmanAnalyzer_Analyze(t *testing.T) { { FilePath: "var/lib/pacman/local/bash-5.1.008-1/desc", Packages: []types.Package{ - {Name: "bash", Version: "5.1.008-1", SrcName: "bash", SrcVersion: "5.1.008-1", Arch: "x86_64", License: "GPL"}, + {Name: "bash", Version: "5.1.008", Release: "1", SrcName: "bash", SrcVersion: "5.1.008", SrcRelease: "1", Arch: "x86_64", License: "GPL"}, }, }, }, From b1d3c63b734db2abfe1fc8c8da5dcf4f277d63fa Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Fri, 17 Sep 2021 05:07:47 +0900 Subject: [PATCH 5/8] refactor(pacman): refactoring parse version --- analyzer/pkg/pacman/pacman.go | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/analyzer/pkg/pacman/pacman.go b/analyzer/pkg/pacman/pacman.go index 7e3d25704..47213ac32 100644 --- a/analyzer/pkg/pacman/pacman.go +++ b/analyzer/pkg/pacman/pacman.go @@ -60,32 +60,32 @@ func (a pacmanAnalyzer) parsePacmanPkgDesc(scanner *bufio.Scanner) (types.Packag } } else if strings.HasPrefix(line, "%VERSION%") { if scanner.Scan() { - version := scanner.Text() - if strings.Contains(version, ":") { - ss := strings.Split(version, ":") - epoch, err := strconv.Atoi(ss[0]) + var ( + epoch int + version string + release string + ) + + ss := strings.Split(scanner.Text(), "-") + release = ss[1] + if strings.Contains(ss[0], ":") { + ss := strings.Split(ss[0], ":") + var err error + epoch, err = strconv.Atoi(ss[0]) if err != nil { return types.Package{}, xerrors.Errorf("failed to convert epoch: %w", err) } - ss = strings.Split(ss[1], "-") - version := ss[0] - release := ss[1] - - pkg.Epoch = epoch - pkg.Version = version - pkg.Release = release - pkg.SrcEpoch = epoch - pkg.SrcVersion = version - pkg.SrcRelease = release + version = ss[1] } else { - ss := strings.Split(version, "-") - version := ss[0] - release := ss[1] - pkg.Version = version - pkg.Release = release - pkg.SrcVersion = version - pkg.SrcRelease = release + version = ss[0] } + + pkg.Epoch = epoch + pkg.Version = version + pkg.Release = release + pkg.SrcEpoch = epoch + pkg.SrcVersion = version + pkg.SrcRelease = release } } else if strings.HasPrefix(line, "%BASE%") { if scanner.Scan() { From e00baa9a4fe2e528be25744a69b565aa06f7bac0 Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Fri, 17 Sep 2021 05:44:24 +0900 Subject: [PATCH 6/8] chore: change version parse --- analyzer/pkg/pacman/pacman.go | 44 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/analyzer/pkg/pacman/pacman.go b/analyzer/pkg/pacman/pacman.go index 47213ac32..6c2c26822 100644 --- a/analyzer/pkg/pacman/pacman.go +++ b/analyzer/pkg/pacman/pacman.go @@ -60,32 +60,36 @@ func (a pacmanAnalyzer) parsePacmanPkgDesc(scanner *bufio.Scanner) (types.Packag } } else if strings.HasPrefix(line, "%VERSION%") { if scanner.Scan() { - var ( - epoch int - version string - release string - ) - - ss := strings.Split(scanner.Text(), "-") - release = ss[1] - if strings.Contains(ss[0], ":") { - ss := strings.Split(ss[0], ":") + var version string + splitted := strings.SplitN(scanner.Text(), ":", 2) + if len(splitted) == 1 { + pkg.Epoch = 0 + version = splitted[0] + } else { var err error - epoch, err = strconv.Atoi(ss[0]) + pkg.Epoch, err = strconv.Atoi(splitted[0]) if err != nil { return types.Package{}, xerrors.Errorf("failed to convert epoch: %w", err) } - version = ss[1] - } else { - version = ss[0] + + if pkg.Epoch < 0 { + return types.Package{}, xerrors.Errorf("epoch is negative") + } + version = splitted[1] } - pkg.Epoch = epoch - pkg.Version = version - pkg.Release = release - pkg.SrcEpoch = epoch - pkg.SrcVersion = version - pkg.SrcRelease = release + index := strings.Index(version, "-") + if index >= 0 { + ver := version[:index] + rel := version[index+1:] + pkg.Version = ver + pkg.Release = rel + pkg.SrcVersion = ver + pkg.SrcRelease = rel + } else { + pkg.Version = version + pkg.SrcVersion = version + } } } else if strings.HasPrefix(line, "%BASE%") { if scanner.Scan() { From f9b3423113c297453f2e09aaf8623cc8dda54094 Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Fri, 17 Sep 2021 08:26:46 +0900 Subject: [PATCH 7/8] feat(pacman): check if version is valid --- analyzer/pkg/pacman/pacman.go | 11 +++++++++-- go.mod | 1 + go.sum | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/analyzer/pkg/pacman/pacman.go b/analyzer/pkg/pacman/pacman.go index 6c2c26822..27d0e3c87 100644 --- a/analyzer/pkg/pacman/pacman.go +++ b/analyzer/pkg/pacman/pacman.go @@ -3,11 +3,14 @@ package pacman import ( "bufio" "bytes" + "log" "os" "path/filepath" "strconv" "strings" + pacmanVersion "github.com/MaineK00n/go-pacman-version" + "github.com/aquasecurity/fanal/analyzer" "github.com/aquasecurity/fanal/types" "golang.org/x/xerrors" @@ -60,8 +63,12 @@ func (a pacmanAnalyzer) parsePacmanPkgDesc(scanner *bufio.Scanner) (types.Packag } } else if strings.HasPrefix(line, "%VERSION%") { if scanner.Scan() { - var version string - splitted := strings.SplitN(scanner.Text(), ":", 2) + version := scanner.Text() + if !pacmanVersion.Valid(version) { + log.Printf("Invalid Version Found : OS %s, Package %s, Version %s", "arch", pkg.Name, version) + continue + } + splitted := strings.SplitN(version, ":", 2) if len(splitted) == 1 { pkg.Epoch = 0 version = splitted[0] diff --git a/go.mod b/go.mod index 58475b1b5..ecf2a4998 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 github.com/BurntSushi/toml v1.0.0 github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0 + github.com/MaineK00n/go-pacman-version v0.0.0-20210916231937-19e87b7d7184 github.com/alicebob/miniredis/v2 v2.18.0 github.com/aquasecurity/defsec v0.14.0 github.com/aquasecurity/go-dep-parser v0.0.0-20220302151315-ff6d77c26988 diff --git a/go.sum b/go.sum index c4d59a1cb..297da4825 100644 --- a/go.sum +++ b/go.sum @@ -143,6 +143,8 @@ github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0 h1:wykTgKwhVr2t2qs+xI020s6W5dt614QqCHV+7W9dg64= github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= +github.com/MaineK00n/go-pacman-version v0.0.0-20210916231937-19e87b7d7184 h1:enu2psM1AcUsNx36T+X13lcy2kmFFV4kwCMmL7i4yiQ= +github.com/MaineK00n/go-pacman-version v0.0.0-20210916231937-19e87b7d7184/go.mod h1:iMNOZ59Aouwx++SN7zGEi8yB9JTd+ZwYufdnC02mjd4= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= From 6878696efd2d4e85586a7803ba908cd792cb360e Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Mon, 17 Jan 2022 00:05:44 +0900 Subject: [PATCH 8/8] fix(arch): replace from AnalysisTarget to AnalysisInput --- analyzer/os/archlinux/archlinux.go | 6 +++--- analyzer/os/archlinux/archlinux_test.go | 10 +++++++--- analyzer/pkg/pacman/pacman.go | 10 +++++----- analyzer/pkg/pacman/pacman_test.go | 10 +++++++--- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/analyzer/os/archlinux/archlinux.go b/analyzer/os/archlinux/archlinux.go index 65bab6f76..590e358a2 100644 --- a/analyzer/os/archlinux/archlinux.go +++ b/analyzer/os/archlinux/archlinux.go @@ -2,7 +2,7 @@ package archlinux import ( "bufio" - "bytes" + "context" "os" "strings" @@ -26,8 +26,8 @@ var requiredFiles = []string{ type archlinuxOSAnalyzer struct{} -func (a archlinuxOSAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.AnalysisResult, error) { - scanner := bufio.NewScanner(bytes.NewBuffer(target.Content)) +func (a archlinuxOSAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { + scanner := bufio.NewScanner(input.Content) for scanner.Scan() { line := scanner.Text() if strings.HasPrefix(line, "NAME=\"Arch Linux") { diff --git a/analyzer/os/archlinux/archlinux_test.go b/analyzer/os/archlinux/archlinux_test.go index 77ac7fb9e..7cc8c9a7f 100644 --- a/analyzer/os/archlinux/archlinux_test.go +++ b/analyzer/os/archlinux/archlinux_test.go @@ -1,6 +1,7 @@ package archlinux import ( + "context" "os" "testing" @@ -34,12 +35,15 @@ func Test_archlinuxOSAnalyzer_Analyze(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { a := archlinuxOSAnalyzer{} - b, err := os.ReadFile(tt.inputFile) + f, err := os.Open(tt.inputFile) require.NoError(t, err) + defer f.Close() - got, err := a.Analyze(analyzer.AnalysisTarget{ + ctx := context.Background() + + got, err := a.Analyze(ctx, analyzer.AnalysisInput{ FilePath: "etc/os-release", - Content: b, + Content: f, }) if tt.wantErr != "" { require.Error(t, err) diff --git a/analyzer/pkg/pacman/pacman.go b/analyzer/pkg/pacman/pacman.go index 27d0e3c87..354c03af3 100644 --- a/analyzer/pkg/pacman/pacman.go +++ b/analyzer/pkg/pacman/pacman.go @@ -2,7 +2,7 @@ package pacman import ( "bufio" - "bytes" + "context" "log" "os" "path/filepath" @@ -26,9 +26,9 @@ const installDir = "var/lib/pacman/local/" type pacmanAnalyzer struct{} -func (a pacmanAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.AnalysisResult, error) { - scanner := bufio.NewScanner(bytes.NewBuffer(target.Content)) - dir, fileName := filepath.Split(target.FilePath) +func (a pacmanAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { + scanner := bufio.NewScanner(input.Content) + dir, fileName := filepath.Split(input.FilePath) if !strings.HasPrefix(dir, installDir) { return nil, nil } @@ -39,7 +39,7 @@ func (a pacmanAnalyzer) Analyze(target analyzer.AnalysisTarget) (*analyzer.Analy } return &analyzer.AnalysisResult{ PackageInfos: []types.PackageInfo{ - {FilePath: target.FilePath, Packages: []types.Package{pkg}}, + {FilePath: input.FilePath, Packages: []types.Package{pkg}}, }, }, nil } diff --git a/analyzer/pkg/pacman/pacman_test.go b/analyzer/pkg/pacman/pacman_test.go index 2c98a4819..920b622d1 100644 --- a/analyzer/pkg/pacman/pacman_test.go +++ b/analyzer/pkg/pacman/pacman_test.go @@ -1,6 +1,7 @@ package pacman import ( + "context" "os" "testing" @@ -204,13 +205,16 @@ func Test_pacmanAnalyzer_Analyze(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - b, err := os.ReadFile(tt.testFile) + f, err := os.Open(tt.testFile) require.NoError(t, err) + defer f.Close() + + ctx := context.Background() a := pacmanAnalyzer{} - got, err := a.Analyze(analyzer.AnalysisTarget{ + got, err := a.Analyze(ctx, analyzer.AnalysisInput{ FilePath: tt.filepath, - Content: b, + Content: f, }) require.NoError(t, err)