syft/syft/pkg/cataloger/swipl/parse_pack.go
Will Murphy e38851143e
chore: centralize temp files and prefer streaming IO (#4668)
* chore: centralize temp files and prefer streaming IO

Catalogers that create temp files ad-hoc can easily forget cleanup,
leaking files on disk. Similarly, io.ReadAll is convenient but risks
OOM on large or malicious inputs.

Introduce internal/tmpdir to manage all cataloger temp storage under
a single root directory with automatic cleanup. Prefer streaming
parsers (bufio.Scanner, json/yaml.NewDecoder, io.LimitReader) over
buffering entire inputs into memory. Add ruleguard rules to enforce
both practices going forward.

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* chore: go back to old release parsing

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* simplify to limit reader in version check

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* chore: regex change postponed

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* simplify supplement release to limitreader

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

---------

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>
2026-03-18 10:53:51 -04:00

73 lines
1.8 KiB
Go

package swipl
import (
"context"
"io"
"regexp"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/generic"
)
func parsePackPackage(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var pkgs []pkg.Package
nameRe := regexp.MustCompile(`name\(\s*'?([^')]+)'?\s*\)`)
versionRe := regexp.MustCompile(`version\('([^']+)'\)`)
homeRe := regexp.MustCompile(`home\(\s*'([^']+)'\s*\)`)
authorRe := regexp.MustCompile(`(author|packager)\(\s*'([^']+)'\s*(?:,\s*'([^']+)'\s*)?\)`)
data, err := io.ReadAll(reader) //nolint:gocritic // regex matching requires full buffer
if err != nil {
log.WithFields("error", err).Trace("unable to parse Rockspec app")
return nil, nil, nil
}
name := nameRe.FindSubmatch(data)
version := versionRe.FindSubmatch(data)
if name == nil || version == nil {
log.Debugf("encountered pack.pl file without a name and/or version field, ignoring (path=%q)", reader.Path())
return nil, nil, nil
}
entry := pkg.SwiplPackEntry{
Name: string(name[1]),
Version: string(version[1]),
}
home := homeRe.FindSubmatch(data)
if home != nil {
entry.Homepage = string(home[1])
}
authors := authorRe.FindAllSubmatch(data, -1)
for _, a := range authors {
switch string(a[1]) {
case "author":
entry.Author = string(a[2])
entry.AuthorEmail = string(a[3])
case "packager":
entry.Packager = string(a[2])
entry.PackagerEmail = string(a[3])
}
}
pkgs = append(
pkgs,
newSwiplPackPackage(
ctx,
resolver,
entry,
reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
)
return pkgs, nil, nil
}