From a0a0b49cbe60eeebe5b740b08e409ab7fe650530 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Mon, 12 Feb 2024 12:46:26 +0400 Subject: [PATCH] fix: lint errors Signed-off-by: knqyf263 --- pkg/dependency/parser/java/jar/parse.go | 99 +++++++++++-------- pkg/dependency/parser/java/pom/parse.go | 51 ++++++---- pkg/dependency/parser/java/pom/pom.go | 26 ++--- .../parser/julia/manifest/naive_pkg_parser.go | 9 +- pkg/dependency/parser/julia/manifest/parse.go | 15 ++- pkg/dependency/parser/nodejs/npm/parse.go | 16 +-- pkg/dependency/parser/nodejs/yarn/parse.go | 2 +- .../parser/nuget/packagesprops/parse.go | 2 +- pkg/dependency/parser/python/pip/parse.go | 2 +- pkg/dependency/parser/rust/binary/parse.go | 38 +++---- .../parser/rust/cargo/naive_pkg_parser.go | 9 +- 11 files changed, 153 insertions(+), 116 deletions(-) diff --git a/pkg/dependency/parser/java/jar/parse.go b/pkg/dependency/parser/java/jar/parse.go index fc0da74f4d66..bf1cd816b08a 100644 --- a/pkg/dependency/parser/java/jar/parse.go +++ b/pkg/dependency/parser/java/jar/parse.go @@ -3,8 +3,9 @@ package jar import ( "archive/zip" "bufio" - "crypto/sha1" + "crypto/sha1" // nolint:gosec "encoding/hex" + "errors" "fmt" dio "github.com/aquasecurity/trivy/pkg/dependency/parser/io" "github.com/aquasecurity/trivy/pkg/dependency/parser/log" @@ -81,46 +82,14 @@ func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, func (p *Parser) parseArtifact(filePath string, size int64, r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) { log.Logger.Debugw("Parsing Java artifacts...", zap.String("file", filePath)) - zr, err := zip.NewReader(r, size) - if err != nil { - return nil, nil, xerrors.Errorf("zip error: %w", err) - } - // Try to extract artifactId and version from the file name // e.g. spring-core-5.3.4-SNAPSHOT.jar => sprint-core, 5.3.4-SNAPSHOT fileName := filepath.Base(filePath) fileProps := parseFileName(filePath) - var libs []types.Library - var m manifest - var foundPomProps bool - - for _, fileInJar := range zr.File { - switch { - case filepath.Base(fileInJar.Name) == "pom.properties": - props, err := parsePomProperties(fileInJar, filePath) - if err != nil { - return nil, nil, xerrors.Errorf("failed to parse %s: %w", fileInJar.Name, err) - } - libs = append(libs, props.Library()) - - // Check if the pom.properties is for the original JAR/WAR/EAR - if fileProps.ArtifactID == props.ArtifactID && fileProps.Version == props.Version { - foundPomProps = true - } - case filepath.Base(fileInJar.Name) == "MANIFEST.MF": - m, err = parseManifest(fileInJar) - if err != nil { - return nil, nil, xerrors.Errorf("failed to parse MANIFEST.MF: %w", err) - } - case isArtifact(fileInJar.Name): - innerLibs, _, err := p.parseInnerJar(fileInJar, filePath) //TODO process inner deps - if err != nil { - log.Logger.Debugf("Failed to parse %s: %s", fileInJar.Name, err) - continue - } - libs = append(libs, innerLibs...) - } + libs, m, foundPomProps, err := p.traverseZip(filePath, size, r, fileProps) + if err != nil { + return nil, nil, xerrors.Errorf("zip error: %w", err) } // If pom.properties is found, it should be preferred than MANIFEST.MF. @@ -151,7 +120,7 @@ func (p *Parser) parseArtifact(filePath string, size int64, r dio.ReadSeekerAt) props, err := p.searchBySHA1(r, filePath) if err == nil { return append(libs, props.Library()), nil, nil - } else if !xerrors.Is(err, ArtifactNotFoundErr) { + } else if !errors.Is(err, ArtifactNotFoundErr) { return nil, nil, xerrors.Errorf("failed to search by SHA1: %w", err) } @@ -169,13 +138,54 @@ func (p *Parser) parseArtifact(filePath string, size int64, r dio.ReadSeekerAt) log.Logger.Debugw("POM was determined in a heuristic way", zap.String("file", fileName), zap.String("artifact", fileProps.String())) libs = append(libs, fileProps.Library()) - } else if !xerrors.Is(err, ArtifactNotFoundErr) { + } else if !errors.Is(err, ArtifactNotFoundErr) { return nil, nil, xerrors.Errorf("failed to search by artifact id: %w", err) } return libs, nil, nil } +func (p *Parser) traverseZip(filePath string, size int64, r dio.ReadSeekerAt, fileProps Properties) ( + []types.Library, manifest, bool, error) { + var libs []types.Library + var m manifest + var foundPomProps bool + + zr, err := zip.NewReader(r, size) + if err != nil { + return nil, manifest{}, false, xerrors.Errorf("zip error: %w", err) + } + + for _, fileInJar := range zr.File { + switch { + case filepath.Base(fileInJar.Name) == "pom.properties": + props, err := parsePomProperties(fileInJar, filePath) + if err != nil { + return nil, manifest{}, false, xerrors.Errorf("failed to parse %s: %w", fileInJar.Name, err) + } + libs = append(libs, props.Library()) + + // Check if the pom.properties is for the original JAR/WAR/EAR + if fileProps.ArtifactID == props.ArtifactID && fileProps.Version == props.Version { + foundPomProps = true + } + case filepath.Base(fileInJar.Name) == "MANIFEST.MF": + m, err = parseManifest(fileInJar) + if err != nil { + return nil, manifest{}, false, xerrors.Errorf("failed to parse MANIFEST.MF: %w", err) + } + case isArtifact(fileInJar.Name): + innerLibs, _, err := p.parseInnerJar(fileInJar, filePath) //TODO process inner deps + if err != nil { + log.Logger.Debugf("Failed to parse %s: %s", fileInJar.Name, err) + continue + } + libs = append(libs, innerLibs...) + } + } + return libs, m, foundPomProps, nil +} + func (p *Parser) parseInnerJar(zf *zip.File, rootPath string) ([]types.Library, []types.Dependency, error) { fr, err := zf.Open() if err != nil { @@ -187,17 +197,22 @@ func (p *Parser) parseInnerJar(zf *zip.File, rootPath string) ([]types.Library, return nil, nil, xerrors.Errorf("unable to create a temp file: %w", err) } defer func() { - f.Close() - os.Remove(f.Name()) + _ = f.Close() + _ = os.Remove(f.Name()) }() // Copy the file content to the temp file - if _, err = io.Copy(f, fr); err != nil { + if n, err := io.CopyN(f, fr, int64(zf.UncompressedSize64)); err != nil { return nil, nil, xerrors.Errorf("file copy error: %w", err) + } else if n != int64(zf.UncompressedSize64) { + return nil, nil, xerrors.Errorf("file copy size error: %w", err) } // build full path to inner jar fullPath := path.Join(rootPath, zf.Name) + if !strings.HasPrefix(fullPath, filepath.Clean(fullPath)) { + return nil, nil, nil // zip slip + } // Parse jar/war/ear recursively innerLibs, innerDeps, err := p.parseArtifact(fullPath, int64(zf.UncompressedSize64), f) @@ -213,7 +228,7 @@ func (p *Parser) searchBySHA1(r io.ReadSeeker, filePath string) (Properties, err return Properties{}, xerrors.Errorf("file seek error: %w", err) } - h := sha1.New() + h := sha1.New() // nolint:gosec if _, err := io.Copy(h, r); err != nil { return Properties{}, xerrors.Errorf("unable to calculate SHA-1: %w", err) } diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 5c6337aac610..aaba398dad57 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -3,6 +3,7 @@ package pom import ( "encoding/xml" "fmt" + "go.uber.org/zap" "io" "net/http" "net/url" @@ -589,8 +590,7 @@ func (p *parser) tryRepository(groupID, artifactID, version string) (*pom, error // e.g. com.fasterxml.jackson.core, jackson-annotations, 2.10.0 // => com/fasterxml/jackson/core/jackson-annotations/2.10.0/jackson-annotations-2.10.0.pom paths := strings.Split(groupID, ".") - paths = append(paths, artifactID, version) - paths = append(paths, fmt.Sprintf("%s-%s.pom", artifactID, version)) + paths = append(paths, artifactID, version, fmt.Sprintf("%s-%s.pom", artifactID, version)) // Search local remoteRepositories loaded, err := p.loadPOMFromLocalRepository(paths) @@ -599,7 +599,7 @@ func (p *parser) tryRepository(groupID, artifactID, version string) (*pom, error } // Search remote remoteRepositories - loaded, err = p.fetchPOMFromRemoteRepository(paths) + loaded, err = p.fetchPOMFromRemoteRepositories(paths) if err == nil { return loaded, nil } @@ -614,7 +614,7 @@ func (p *parser) loadPOMFromLocalRepository(paths []string) (*pom, error) { return p.openPom(localPath) } -func (p *parser) fetchPOMFromRemoteRepository(paths []string) (*pom, error) { +func (p *parser) fetchPOMFromRemoteRepositories(paths []string) (*pom, error) { // Do not try fetching pom.xml from remote repositories in offline mode if p.offline { log.Logger.Debug("Fetching the remote pom.xml is skipped") @@ -623,30 +623,41 @@ func (p *parser) fetchPOMFromRemoteRepository(paths []string) (*pom, error) { // try all remoteRepositories for _, repo := range p.remoteRepositories { - repoURL, err := url.Parse(repo) + fetched, err := fetchPOMFromRemoteRepository(repo, paths) if err != nil { + return nil, xerrors.Errorf("fetch repository error: %w", err) + } else if fetched == nil { continue } + return fetched, nil + } + return nil, xerrors.Errorf("the POM was not found in remote remoteRepositories") +} - paths = append([]string{repoURL.Path}, paths...) - repoURL.Path = path.Join(paths...) +func fetchPOMFromRemoteRepository(repo string, paths []string) (*pom, error) { + repoURL, err := url.Parse(repo) + if err != nil { + log.Logger.Errorw("URL parse error", zap.String("repo", repo)) + return nil, nil + } - resp, err := http.Get(repoURL.String()) - if err != nil || resp.StatusCode != http.StatusOK { - continue - } + paths = append([]string{repoURL.Path}, paths...) + repoURL.Path = path.Join(paths...) - content, err := parsePom(resp.Body) - if err != nil { - return nil, xerrors.Errorf("failed to parse the remote POM: %w", err) - } + resp, err := http.Get(repoURL.String()) + if err != nil || resp.StatusCode != http.StatusOK { + return nil, nil + } - return &pom{ - filePath: "", // from remote repositories - content: content, - }, nil + content, err := parsePom(resp.Body) + if err != nil { + return nil, xerrors.Errorf("failed to parse the remote POM: %w", err) } - return nil, xerrors.Errorf("the POM was not found in remote remoteRepositories") + + return &pom{ + filePath: "", // from remote repositories + content: content, + }, nil } func parsePom(r io.Reader) (*pomXML, error) { diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index fe7ca69b941a..91213e9797ca 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -323,22 +323,22 @@ func (deps *pomDependencies) UnmarshalXML(d *xml.Decoder, _ xml.StartElement) er return xerrors.Errorf("XML decode error: %w", err) } - switch t := token.(type) { - case xml.StartElement: - if t.Name.Local == "dependency" { - var dep pomDependency - dep.StartLine, _ = d.InputPos() // tag starts - - // Decode the element - err = d.DecodeElement(&dep, &t) - if err != nil { - return xerrors.Errorf("Error decoding dependency: %w") - } + t, ok := token.(xml.StartElement) + if !ok { + continue + } - dep.EndLine, _ = d.InputPos() // tag ends + if t.Name.Local == "dependency" { + var dep pomDependency + dep.StartLine, _ = d.InputPos() // tag starts - deps.Dependency = append(deps.Dependency, dep) + // Decode the element + err = d.DecodeElement(&dep, &t) + if err != nil { + return xerrors.Errorf("Error decoding dependency: %w") } + + dep.EndLine, _ = d.InputPos() // tag ends } } return nil diff --git a/pkg/dependency/parser/julia/manifest/naive_pkg_parser.go b/pkg/dependency/parser/julia/manifest/naive_pkg_parser.go index b1c240871d5e..21f899ca177a 100644 --- a/pkg/dependency/parser/julia/manifest/naive_pkg_parser.go +++ b/pkg/dependency/parser/julia/manifest/naive_pkg_parser.go @@ -34,7 +34,8 @@ func (parser *naivePkgParser) parse() map[string]pkgPosition { lineNum := 1 for scanner.Scan() { line := scanner.Text() - if strings.HasPrefix(strings.TrimSpace(line), "[") { + switch { + case strings.HasPrefix(strings.TrimSpace(line), "["): if currentPkg.uuid != "" { currentPkg.setEndPositionIfEmpty(lineNum - 1) idx[currentPkg.uuid] = currentPkg.position @@ -42,11 +43,11 @@ func (parser *naivePkgParser) parse() map[string]pkgPosition { currentPkg = minPkg{} currentPkg.position.start = lineNum - } else if strings.HasPrefix(strings.TrimSpace(line), "uuid =") { + case strings.HasPrefix(strings.TrimSpace(line), "uuid ="): currentPkg.uuid = propertyValue(line) - } else if strings.HasPrefix(strings.TrimSpace(line), "version =") { + case strings.HasPrefix(strings.TrimSpace(line), "version ="): currentPkg.version = propertyValue(line) - } else if strings.TrimSpace(line) == "" { + case strings.TrimSpace(line) == "": currentPkg.setEndPositionIfEmpty(lineNum - 1) } diff --git a/pkg/dependency/parser/julia/manifest/parse.go b/pkg/dependency/parser/julia/manifest/parse.go index aa5e21ef6d57..211b3be4ad4b 100644 --- a/pkg/dependency/parser/julia/manifest/parse.go +++ b/pkg/dependency/parser/julia/manifest/parse.go @@ -72,7 +72,7 @@ func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, var deps []types.Dependency for name, manifestDeps := range man.Dependencies { for _, manifestDep := range manifestDeps { - version := depVersion(&manifestDep, man.JuliaVersion) + version := depVersion(manifestDep.Version, man.JuliaVersion) pkgID := manifestDep.UUID lib := types.Library{ ID: pkgID, @@ -80,7 +80,12 @@ func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, Version: version, } if pos, ok := lineNumIdx[manifestDep.UUID]; ok { - lib.Locations = []types.Location{{StartLine: pos.start, EndLine: pos.end}} + lib.Locations = []types.Location{ + { + StartLine: pos.start, + EndLine: pos.end, + }, + } } libs = append(libs, lib) @@ -100,11 +105,11 @@ func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, // Returns the effective version of the `dep`. // stdlib packages do not have a version in the manifest because they are packaged with julia itself -func depVersion(dep *primitiveDependency, juliaVersion string) string { - if len(dep.Version) == 0 { +func depVersion(depVersion, juliaVersion string) string { + if depVersion == "" { return juliaVersion } - return dep.Version + return depVersion } // Decodes a primitive manifest using the metadata from parse time. diff --git a/pkg/dependency/parser/nodejs/npm/parse.go b/pkg/dependency/parser/nodejs/npm/parse.go index e0490edf92b5..8937f718da50 100644 --- a/pkg/dependency/parser/nodejs/npm/parse.go +++ b/pkg/dependency/parser/nodejs/npm/parse.go @@ -233,10 +233,10 @@ func findDependsOn(pkgPath, depName string, packages map[string]Package) (string if paths[i] != nodeModulesDir { continue } - path := joinPaths(paths[:i+1]...) - path = joinPaths(path, depName) + modulePath := joinPaths(paths[:i+1]...) + modulePath = joinPaths(modulePath, depName) - if dep, ok := packages[path]; ok { + if dep, ok := packages[modulePath]; ok { return utils.PackageID(depName, dep.Version), nil } } @@ -340,18 +340,18 @@ func isIndirectLib(pkgPath string, directDeps map[string]struct{}) bool { return true } -func pkgNameFromPath(path string) string { +func pkgNameFromPath(pkgPath string) string { // lock file contains path to dependency in `node_modules`. e.g.: // node_modules/string-width // node_modules/string-width/node_modules/strip-ansi // we renamed to `node_modules` directory prefixes `workspace` when resolving Links // node_modules/function1 // node_modules/nested_func/node_modules/debug - if index := strings.LastIndex(path, nodeModulesDir); index != -1 { - return path[index+len(nodeModulesDir)+1:] + if index := strings.LastIndex(pkgPath, nodeModulesDir); index != -1 { + return pkgPath[index+len(nodeModulesDir)+1:] } - log.Logger.Warnf("npm %q package path doesn't have `node_modules` prefix", path) - return path + log.Logger.Warnf("npm %q package path doesn't have `node_modules` prefix", pkgPath) + return pkgPath } func joinPaths(paths ...string) string { diff --git a/pkg/dependency/parser/nodejs/yarn/parse.go b/pkg/dependency/parser/nodejs/yarn/parse.go index 7832bdeac631..1f28581e60c6 100644 --- a/pkg/dependency/parser/nodejs/yarn/parse.go +++ b/pkg/dependency/parser/nodejs/yarn/parse.go @@ -175,7 +175,7 @@ func parseBlock(block []byte, lineNum int) (lib Library, deps []string, newLine for scanner.Scan() { line := scanner.Text() - if len(line) == 0 { + if line == "" { emptyLines++ continue } diff --git a/pkg/dependency/parser/nuget/packagesprops/parse.go b/pkg/dependency/parser/nuget/packagesprops/parse.go index 35eebc27101b..6096c8948fb4 100644 --- a/pkg/dependency/parser/nuget/packagesprops/parse.go +++ b/pkg/dependency/parser/nuget/packagesprops/parse.go @@ -51,7 +51,7 @@ func (p pkg) library() types.Library { } func shouldSkipLib(lib types.Library) bool { - if len(lib.Name) == 0 || len(lib.Version) == 0 { + if lib.Name == "" || lib.Version == "" { return true } // *packages.props files don't contain variable resolution information. diff --git a/pkg/dependency/parser/python/pip/parse.go b/pkg/dependency/parser/python/pip/parse.go index 80e881a25b31..99438495791b 100644 --- a/pkg/dependency/parser/python/pip/parse.go +++ b/pkg/dependency/parser/python/pip/parse.go @@ -58,7 +58,7 @@ func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, return libs, nil, nil } -func rStripByKey(line string, key string) string { +func rStripByKey(line, key string) string { if pos := strings.Index(line, key); pos >= 0 { line = strings.TrimRightFunc((line)[:pos], unicode.IsSpace) } diff --git a/pkg/dependency/parser/rust/binary/parse.go b/pkg/dependency/parser/rust/binary/parse.go index 5c26831a3512..d426cc347989 100644 --- a/pkg/dependency/parser/rust/binary/parse.go +++ b/pkg/dependency/parser/rust/binary/parse.go @@ -45,26 +45,30 @@ func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, var libs []types.Library var deps []types.Dependency for _, pkg := range info.Packages { - if pkg.Kind == rustaudit.Runtime { - pkgID := utils.PackageID(pkg.Name, pkg.Version) - libs = append(libs, types.Library{ - ID: pkgID, - Name: pkg.Name, - Version: pkg.Version, - Indirect: !pkg.Root, - }) + if pkg.Kind != rustaudit.Runtime { + continue + } + pkgID := utils.PackageID(pkg.Name, pkg.Version) + libs = append(libs, types.Library{ + ID: pkgID, + Name: pkg.Name, + Version: pkg.Version, + Indirect: !pkg.Root, + }) - var childDeps []string - for _, dep_idx := range pkg.Dependencies { - dep := info.Packages[dep_idx] - if dep.Kind == rustaudit.Runtime { - childDeps = append(childDeps, utils.PackageID(dep.Name, dep.Version)) - } - } - if len(childDeps) > 0 { - deps = append(deps, types.Dependency{ID: pkgID, DependsOn: childDeps}) + var childDeps []string + for _, dep_idx := range pkg.Dependencies { + dep := info.Packages[dep_idx] + if dep.Kind == rustaudit.Runtime { + childDeps = append(childDeps, utils.PackageID(dep.Name, dep.Version)) } } + if len(childDeps) > 0 { + deps = append(deps, types.Dependency{ + ID: pkgID, + DependsOn: childDeps, + }) + } } return libs, deps, nil diff --git a/pkg/dependency/parser/rust/cargo/naive_pkg_parser.go b/pkg/dependency/parser/rust/cargo/naive_pkg_parser.go index 4fefb7f2f752..f12134a7891f 100644 --- a/pkg/dependency/parser/rust/cargo/naive_pkg_parser.go +++ b/pkg/dependency/parser/rust/cargo/naive_pkg_parser.go @@ -37,7 +37,8 @@ func (parser *naivePkgParser) parse() map[string]pkgPosition { lineNum := 1 for scanner.Scan() { line := scanner.Text() - if strings.HasPrefix(strings.TrimSpace(line), "[") { + switch { + case strings.HasPrefix(strings.TrimSpace(line), "["): if currentPkg.name != "" { pkgId := utils.PackageID(currentPkg.name, currentPkg.version) currentPkg.setEndPositionIfEmpty(lineNum - 1) @@ -46,11 +47,11 @@ func (parser *naivePkgParser) parse() map[string]pkgPosition { currentPkg = minPkg{} currentPkg.position.start = lineNum - } else if strings.HasPrefix(strings.TrimSpace(line), "name =") { + case strings.HasPrefix(strings.TrimSpace(line), "name ="): currentPkg.name = propertyValue(line) - } else if strings.HasPrefix(strings.TrimSpace(line), "version =") { + case strings.HasPrefix(strings.TrimSpace(line), "version ="): currentPkg.version = propertyValue(line) - } else if strings.TrimSpace(line) == "" { + case strings.TrimSpace(line) == "": currentPkg.setEndPositionIfEmpty(lineNum - 1) }