mirror of
https://github.com/anchore/syft.git
synced 2026-11-05 17:06:32 +01:00
fix(dpkg): extract License field for opkg/ipkg entries (#4963)
* fix(dpkg): extract License field for opkg/ipkg entries opkg and ipkg use the dpkg cataloger but declare the package License inline in the status DB (unlike Debian dpkg, where licenses live in copyright files). The cataloger silently dropped the License field at mapstructure decode time, so all opkg-managed packages reported empty licenses. This adds the field to the intermediate decode struct and the public DpkgDBEntry, and populates licenses in newDpkgPackage using the alpine cataloger's pattern: try license.ParseExpression first to keep valid SPDX expressions whole, fall back to whitespace splitting for space-separated lists. Standard Debian dpkg status files never carry a License field per Debian policy, so the new path is a no-op for them; the existing copyright-file lookup in addLicenses is unaffected. Closes #4940 Signed-off-by: David Dashti <47575784+Dashtid@users.noreply.github.com> * remove license from dpkg metadata struct Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * restore format snapshot files Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add additional tests Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: David Dashti <47575784+Dashtid@users.noreply.github.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
co-authored by
Alex Goodman
parent
00ca43d24a
commit
cff5a05681
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/license"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
@@ -23,21 +24,26 @@ const (
|
||||
docsPath = "/usr/share/doc"
|
||||
)
|
||||
|
||||
func newDpkgPackage(ctx context.Context, d pkg.DpkgDBEntry, dbLocation file.Location, resolver file.Resolver, release *linux.Release, evidence ...file.Location) pkg.Package {
|
||||
// TODO: separate pr to license refactor, but explore extracting dpkg-specific license parsing into a separate function
|
||||
var licenses []pkg.License
|
||||
func newDpkgPackage(ctx context.Context, d dpkgExtractedMetadata, dbLocation file.Location, resolver file.Resolver, release *linux.Release, evidence ...file.Location) pkg.Package {
|
||||
// the License field is empty for standard Debian dpkg entries (licenses live in copyright files),
|
||||
// but opkg/ipkg derivatives carry it inline in the status DB — extract it here so those packages
|
||||
// report licenses without requiring per-package copyright lookups. The license is not persisted on
|
||||
// the final entry, so convert the raw metadata into the entry just-in-time here.
|
||||
licenses := extractDeclaredLicenses(ctx, d.License, dbLocation)
|
||||
|
||||
entry := d.toDpkgEntry()
|
||||
|
||||
locations := file.NewLocationSet(dbLocation)
|
||||
locations.Add(evidence...)
|
||||
|
||||
p := pkg.Package{
|
||||
Name: d.Package,
|
||||
Version: d.Version,
|
||||
Name: entry.Package,
|
||||
Version: entry.Version,
|
||||
Licenses: pkg.NewLicenseSet(licenses...),
|
||||
Locations: locations,
|
||||
PURL: packageURL(d, release),
|
||||
PURL: packageURL(entry, release),
|
||||
Type: pkg.DebPkg,
|
||||
Metadata: d,
|
||||
Metadata: entry,
|
||||
}
|
||||
|
||||
if resolver != nil {
|
||||
@@ -55,6 +61,21 @@ func newDpkgPackage(ctx context.Context, d pkg.DpkgDBEntry, dbLocation file.Loca
|
||||
return p
|
||||
}
|
||||
|
||||
// extractDeclaredLicenses converts a License field from the status DB into a license set. Returns nil
|
||||
// for empty input so standard dpkg entries (which never declare License inline) incur no allocation.
|
||||
// Mirrors the alpine cataloger's approach: keep the value whole if it parses as a valid SPDX expression,
|
||||
// otherwise split on whitespace to handle space-separated lists.
|
||||
func extractDeclaredLicenses(ctx context.Context, raw string, dbLocation file.Location) []pkg.License {
|
||||
if raw == "" {
|
||||
return nil
|
||||
}
|
||||
licenseStrings := []string{raw}
|
||||
if _, err := license.ParseExpression(raw); err != nil {
|
||||
licenseStrings = strings.Fields(raw)
|
||||
}
|
||||
return pkg.NewLicensesFromLocationWithContext(ctx, dbLocation, licenseStrings...)
|
||||
}
|
||||
|
||||
func newDebArchivePackage(ctx context.Context, location file.Location, metadata pkg.DpkgArchiveEntry, licenseStrings []string) pkg.Package {
|
||||
p := pkg.Package{
|
||||
Name: metadata.Package,
|
||||
|
||||
Reference in New Issue
Block a user