mirror of
https://github.com/anchore/syft.git
synced 2026-11-01 15:06:36 +01:00
* 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>
113 lines
2.8 KiB
Go
113 lines
2.8 KiB
Go
package php
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/elliotchance/phpserialize"
|
|
|
|
"github.com/anchore/syft/internal/unknown"
|
|
"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"
|
|
)
|
|
|
|
type peclPearData struct {
|
|
Name string
|
|
Channel string
|
|
Version string
|
|
License []string
|
|
}
|
|
|
|
func (p *peclPearData) ToPear() pkg.PhpPearEntry {
|
|
return pkg.PhpPearEntry{
|
|
Name: p.Name,
|
|
Channel: p.Channel,
|
|
Version: p.Version,
|
|
License: p.License,
|
|
}
|
|
}
|
|
|
|
func (p *peclPearData) ToPecl() pkg.PhpPeclEntry { //nolint:staticcheck
|
|
return pkg.PhpPeclEntry(p.ToPear()) //nolint:staticcheck
|
|
}
|
|
|
|
func parsePecl(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
|
m, err := parsePeclPearSerialized(reader)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if m == nil {
|
|
return nil, nil, unknown.New(reader.Location, fmt.Errorf("no pecl package found"))
|
|
}
|
|
return []pkg.Package{newPeclPackage(ctx, *m, reader.Location)}, nil, nil
|
|
}
|
|
|
|
func parsePear(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
|
m, err := parsePeclPearSerialized(reader)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if m == nil {
|
|
return nil, nil, unknown.New(reader.Location, fmt.Errorf("no pear package found"))
|
|
}
|
|
return []pkg.Package{newPearPackage(ctx, *m, reader.Location)}, nil, nil
|
|
}
|
|
|
|
// parsePeclPearSerialized is a parser function for Pear metadata contents, returning "Default" php packages discovered.
|
|
func parsePeclPearSerialized(reader file.LocationReadCloser) (*peclPearData, error) {
|
|
data, err := io.ReadAll(reader) //nolint:gocritic // phpserialize requires []byte
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read file: %w", err)
|
|
}
|
|
|
|
metadata, err := phpserialize.UnmarshalAssociativeArray(
|
|
data,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse pear metadata file: %w", err)
|
|
}
|
|
|
|
name, ok := metadata["name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("failed to parse pear package name: %w", err)
|
|
}
|
|
|
|
channel, ok := metadata["channel"].(string)
|
|
if !ok {
|
|
// this could be the v5 format
|
|
channel = ""
|
|
}
|
|
|
|
version := readStruct(metadata, "version", "release")
|
|
license := readStruct(metadata, "license", "_content")
|
|
|
|
return &peclPearData{
|
|
Name: name,
|
|
Channel: channel,
|
|
Version: version,
|
|
License: []string{
|
|
license,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func readStruct(metadata any, fields ...string) string {
|
|
if len(fields) > 0 {
|
|
value, ok := metadata.(map[any]any)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
return readStruct(value[fields[0]], fields[1:]...)
|
|
}
|
|
value, ok := metadata.(string)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
return value
|
|
}
|