config: move symbol enum to cataloging pkg

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
Christopher Phillips 2026-07-01 02:11:44 -04:00
parent a1831ce3b4
commit 46f9974fec
No known key found for this signature in database
11 changed files with 87 additions and 71 deletions

View File

@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/anchore/clio" "github.com/anchore/clio"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/pkg/cataloger/golang" "github.com/anchore/syft/syft/pkg/cataloger/golang"
) )
@ -18,7 +19,7 @@ type golangConfig struct {
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"` NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"` MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
UsePackagesLib *bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"` UsePackagesLib *bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
CaptureSymbols golang.SymbolScope `json:"capture-symbols" yaml:"capture-symbols" mapstructure:"capture-symbols"` CaptureSymbols cataloging.SymbolScope `json:"capture-symbols" yaml:"capture-symbols" mapstructure:"capture-symbols"`
} }
var _ interface { var _ interface {

View File

@ -5,30 +5,30 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/pkg/cataloger/golang" "github.com/anchore/syft/syft/cataloging"
) )
func Test_golangConfig_PostLoad(t *testing.T) { func Test_golangConfig_PostLoad(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
cfg golangConfig cfg golangConfig
expected golang.SymbolScope expected cataloging.SymbolScope
wantErr assert.ErrorAssertionFunc wantErr assert.ErrorAssertionFunc
}{ }{
{ {
name: "normalize all", name: "normalize all",
cfg: golangConfig{CaptureSymbols: "all"}, cfg: golangConfig{CaptureSymbols: "all"},
expected: golang.SymbolScopeAll, expected: cataloging.SymbolScopeAll,
}, },
{ {
name: "normalize stdlib", name: "normalize stdlib",
cfg: golangConfig{CaptureSymbols: "stdlib"}, cfg: golangConfig{CaptureSymbols: "stdlib"},
expected: golang.SymbolScopeStdlib, expected: cataloging.SymbolScopeStdlib,
}, },
{ {
name: "empty defaults to none", name: "empty defaults to none",
cfg: golangConfig{CaptureSymbols: ""}, cfg: golangConfig{CaptureSymbols: ""},
expected: golang.SymbolScopeNone, expected: cataloging.SymbolScopeNone,
}, },
{ {
name: "error on invalid value", name: "error on invalid value",

View File

@ -10,6 +10,7 @@ const (
// 16.1.1 - correct elf package osCpe field according to the document of systemd (also add appCpe field) // 16.1.1 - correct elf package osCpe field according to the document of systemd (also add appCpe field)
// 16.1.2 - placeholder for 16.1.2 changelog // 16.1.2 - placeholder for 16.1.2 changelog
// 16.1.3 - add GGUFFileParts to GGUFFileHeader metadata // 16.1.3 - add GGUFFileParts to GGUFFileHeader metadata
// 16.1.4 - add BunLockEntry metadata type for bun.lock support
// 16.1.5 - add DenoLockEntry and DenoRemoteLockEntry metadata types for deno.lock support // 16.1.5 - add DenoLockEntry and DenoRemoteLockEntry metadata types for deno.lock support
// 16.1.6 - add Dependencies to ElixirMixLockEntry metadata // 16.1.6 - add Dependencies to ElixirMixLockEntry metadata
// 16.1.7 - add AppleAppBundleEntry metadata type for the apple app bundle cataloger // 16.1.7 - add AppleAppBundleEntry metadata type for the apple app bundle cataloger

View File

@ -1659,7 +1659,7 @@
"type": "string" "type": "string"
}, },
"type": "array", "type": "array",
"description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nOnly captured when the golang cataloger is configured to capture symbols." "description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nPopulated only when the golang cataloger's capture-symbols scope covers this package: the \"all\" scope\npopulates every module package plus the synthetic stdlib package, while the \"stdlib\" scope populates\nonly the stdlib package."
} }
}, },
"type": "object", "type": "object",

View File

@ -1659,7 +1659,7 @@
"type": "string" "type": "string"
}, },
"type": "array", "type": "array",
"description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nOnly captured when the golang cataloger is configured to capture symbols." "description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nPopulated only when the golang cataloger's capture-symbols scope covers this package: the \"all\" scope\npopulates every module package plus the synthetic stdlib package, while the \"stdlib\" scope populates\nonly the stdlib package."
} }
}, },
"type": "object", "type": "object",

View File

@ -0,0 +1,31 @@
package cataloging
import "strings"
// SymbolScope controls which packages get function symbols (from a binary's symbol table) attached to their metadata.
type SymbolScope string
const (
// SymbolScopeNone disables symbol capture entirely.
SymbolScopeNone SymbolScope = "none"
// SymbolScopeStdlib captures symbols only for the synthetic "stdlib" package, leaving module packages without symbols.
SymbolScopeStdlib SymbolScope = "stdlib"
// SymbolScopeAll captures symbols for all module packages as well as the synthetic "stdlib" package.
SymbolScopeAll SymbolScope = "all"
)
// Parse normalizes a SymbolScope, treating an empty (unset) value as SymbolScopeNone. It returns an empty
// SymbolScope to signal an unrecognized value, which callers validate against.
func (s SymbolScope) Parse() SymbolScope {
switch strings.ToLower(strings.TrimSpace(string(s))) {
case string(SymbolScopeAll):
return SymbolScopeAll
case string(SymbolScopeStdlib):
return SymbolScopeStdlib
case string(SymbolScopeNone), "":
return SymbolScopeNone
}
return ""
}

View File

@ -0,0 +1,30 @@
package cataloging
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_SymbolScope_Parse(t *testing.T) {
tests := []struct {
input string
expected SymbolScope
}{
{"all", SymbolScopeAll},
{"ALL", SymbolScopeAll},
{" all ", SymbolScopeAll},
{"stdlib", SymbolScopeStdlib},
{"Stdlib", SymbolScopeStdlib},
{"none", SymbolScopeNone},
{"", SymbolScopeNone},
{"true", ""},
{"false", ""},
{"bogus", ""},
}
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
assert.Equal(t, test.expected, SymbolScope(test.input).Parse())
})
}
}

View File

@ -7,6 +7,7 @@ import (
"github.com/anchore/go-homedir" "github.com/anchore/go-homedir"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/cataloging"
) )
const ( const (
@ -18,34 +19,6 @@ var (
directProxiesOnly = []string{directProxyOnly} directProxiesOnly = []string{directProxyOnly}
) )
// SymbolScope controls which packages get function symbols (from the binary pclntab) attached to their metadata.
type SymbolScope string
const (
// SymbolScopeNone disables symbol capture entirely.
SymbolScopeNone SymbolScope = "none"
// SymbolScopeStdlib captures symbols only for the synthetic "stdlib" package, leaving module packages without symbols.
SymbolScopeStdlib SymbolScope = "stdlib"
// SymbolScopeAll captures symbols for all module packages as well as the synthetic "stdlib" package.
SymbolScopeAll SymbolScope = "all"
)
// Parse normalizes a SymbolScope, treating an empty (unset) value as SymbolScopeNone. It returns an empty
// SymbolScope to signal an unrecognized value, which callers validate against.
func (s SymbolScope) Parse() SymbolScope {
switch strings.ToLower(strings.TrimSpace(string(s))) {
case string(SymbolScopeAll):
return SymbolScopeAll
case string(SymbolScopeStdlib):
return SymbolScopeStdlib
case string(SymbolScopeNone), "":
return SymbolScopeNone
}
return ""
}
type CatalogerConfig struct { type CatalogerConfig struct {
// SearchLocalModCacheLicenses enables searching for go package licenses in the local GOPATH mod cache. // SearchLocalModCacheLicenses enables searching for go package licenses in the local GOPATH mod cache.
// app-config: golang.search-local-mod-cache-licenses // app-config: golang.search-local-mod-cache-licenses
@ -80,7 +53,7 @@ type CatalogerConfig struct {
// CaptureSymbols controls extracting function symbols from the binary symbol table (pclntab). Valid values are // CaptureSymbols controls extracting function symbols from the binary symbol table (pclntab). Valid values are
// "none" (disabled), "stdlib" (only the synthetic stdlib package), and "all" (all module packages plus stdlib). // "none" (disabled), "stdlib" (only the synthetic stdlib package), and "all" (all module packages plus stdlib).
// app-config: golang.capture-symbols // app-config: golang.capture-symbols
CaptureSymbols SymbolScope `yaml:"capture-symbols" json:"capture-symbols" mapstructure:"capture-symbols"` CaptureSymbols cataloging.SymbolScope `yaml:"capture-symbols" json:"capture-symbols" mapstructure:"capture-symbols"`
// Whether to use the golang.org/x/tools/go/packages, which executes golang tooling found on the path in addition to potential network access // Whether to use the golang.org/x/tools/go/packages, which executes golang tooling found on the path in addition to potential network access
UsePackagesLib bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"` UsePackagesLib bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
@ -109,7 +82,7 @@ func DefaultCatalogerConfig() CatalogerConfig {
UsePackagesLib: true, UsePackagesLib: true,
MainModuleVersion: DefaultMainModuleVersionConfig(), MainModuleVersion: DefaultMainModuleVersionConfig(),
LocalModCacheDir: defaultGoModDir(), LocalModCacheDir: defaultGoModDir(),
CaptureSymbols: SymbolScopeNone, CaptureSymbols: cataloging.SymbolScopeNone,
} }
// first process the proxy settings // first process the proxy settings
@ -218,7 +191,7 @@ func (g CatalogerConfig) WithMainModuleVersion(input MainModuleVersionConfig) Ca
return g return g
} }
func (g CatalogerConfig) WithCaptureSymbols(input SymbolScope) CatalogerConfig { func (g CatalogerConfig) WithCaptureSymbols(input cataloging.SymbolScope) CatalogerConfig {
g.CaptureSymbols = input g.CaptureSymbols = input
return g return g
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/anchore/go-homedir" "github.com/anchore/go-homedir"
"github.com/anchore/syft/syft/cataloging"
) )
func Test_Config(t *testing.T) { func Test_Config(t *testing.T) {
@ -58,7 +59,7 @@ func Test_Config(t *testing.T) {
NoProxy: []string{"my.private", "no.proxy"}, NoProxy: []string{"my.private", "no.proxy"},
MainModuleVersion: DefaultMainModuleVersionConfig(), MainModuleVersion: DefaultMainModuleVersionConfig(),
UsePackagesLib: true, UsePackagesLib: true,
CaptureSymbols: SymbolScopeNone, CaptureSymbols: cataloging.SymbolScopeNone,
}, },
}, },
{ {
@ -87,7 +88,7 @@ func Test_Config(t *testing.T) {
NoProxy: []string{"alt.no.proxy"}, NoProxy: []string{"alt.no.proxy"},
MainModuleVersion: DefaultMainModuleVersionConfig(), MainModuleVersion: DefaultMainModuleVersionConfig(),
UsePackagesLib: true, UsePackagesLib: true,
CaptureSymbols: SymbolScopeNone, CaptureSymbols: cataloging.SymbolScopeNone,
}, },
}, },
} }
@ -114,29 +115,6 @@ func Test_Config(t *testing.T) {
} }
} }
func Test_SymbolScope_Parse(t *testing.T) {
tests := []struct {
input string
expected SymbolScope
}{
{"all", SymbolScopeAll},
{"ALL", SymbolScopeAll},
{" all ", SymbolScopeAll},
{"stdlib", SymbolScopeStdlib},
{"Stdlib", SymbolScopeStdlib},
{"none", SymbolScopeNone},
{"", SymbolScopeNone},
{"true", ""},
{"false", ""},
{"bogus", ""},
}
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
assert.Equal(t, test.expected, SymbolScope(test.input).Parse())
})
}
}
// restoreCache ensures cache settings are restored after test // restoreCache ensures cache settings are restored after test
func restoreCache(t testing.TB) { func restoreCache(t testing.TB) {
t.Helper() t.Helper()

View File

@ -21,6 +21,7 @@ import (
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/unionreader" "github.com/anchore/syft/syft/internal/unionreader"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
@ -50,7 +51,7 @@ const devel = "(devel)"
type goBinaryCataloger struct { type goBinaryCataloger struct {
licenseResolver goLicenseResolver licenseResolver goLicenseResolver
mainModuleVersion MainModuleVersionConfig mainModuleVersion MainModuleVersionConfig
symbolScope SymbolScope symbolScope cataloging.SymbolScope
// stdlibSymbols holds the standard-library function symbols discovered per binary (keyed by the // stdlibSymbols holds the standard-library function symbols discovered per binary (keyed by the
// binary's location), populated during parsing and consumed by stdlibProcessor when it builds the // binary's location), populated during parsing and consumed by stdlibProcessor when it builds the
@ -98,7 +99,7 @@ func (c *goBinaryCataloger) parseGoBinary(ctx context.Context, resolver file.Res
} }
defer internal.CloseAndLogError(reader.ReadCloser, reader.RealPath) defer internal.CloseAndLogError(reader.ReadCloser, reader.RealPath)
mods, errs := scanFile(reader.Location, unionReader, c.symbolScope != SymbolScopeNone) mods, errs := scanFile(reader.Location, unionReader, c.symbolScope != cataloging.SymbolScopeNone)
var rels []artifact.Relationship var rels []artifact.Relationship
for _, mod := range mods { for _, mod := range mods {
@ -161,7 +162,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, resolver file.Re
symbolsByModule, stdlibSymbols := moduleSymbols(mod.symbols, &mod.Main, mod.Deps) symbolsByModule, stdlibSymbols := moduleSymbols(mod.symbols, &mod.Main, mod.Deps)
c.recordStdlibSymbols(location.Coordinates, stdlibSymbols) c.recordStdlibSymbols(location.Coordinates, stdlibSymbols)
if c.symbolScope != SymbolScopeAll { if c.symbolScope != cataloging.SymbolScopeAll {
// only the "all" scope attaches per-module symbols; for the "stdlib" scope we keep just the // only the "all" scope attaches per-module symbols; for the "stdlib" scope we keep just the
// recorded stdlib symbols. nil map lookups below then yield nil symbol lists for each module. // recorded stdlib symbols. nil map lookups below then yield nil symbol lists for each module.
symbolsByModule = nil symbolsByModule = nil

View File

@ -18,6 +18,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/fileresolver" "github.com/anchore/syft/syft/internal/fileresolver"
"github.com/anchore/syft/syft/internal/unionreader" "github.com/anchore/syft/syft/internal/unionreader"
@ -1437,7 +1438,7 @@ func Test_buildGoPkgInfo_symbolScope(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
scope SymbolScope scope cataloging.SymbolScope
symbols []binarySymbol symbols []binarySymbol
wantMainSyms []string wantMainSyms []string
wantDepSyms []string wantDepSyms []string
@ -1445,18 +1446,18 @@ func Test_buildGoPkgInfo_symbolScope(t *testing.T) {
}{ }{
{ {
name: "none captures nothing", name: "none captures nothing",
scope: SymbolScopeNone, scope: cataloging.SymbolScopeNone,
symbols: nil, symbols: nil,
}, },
{ {
name: "stdlib captures only the stdlib package", name: "stdlib captures only the stdlib package",
scope: SymbolScopeStdlib, scope: cataloging.SymbolScopeStdlib,
symbols: populatedSymbols, symbols: populatedSymbols,
wantStdlibSyms: []string{"net/http.(*Client).Do"}, wantStdlibSyms: []string{"net/http.(*Client).Do"},
}, },
{ {
name: "all captures module and stdlib packages", name: "all captures module and stdlib packages",
scope: SymbolScopeAll, scope: cataloging.SymbolScopeAll,
symbols: populatedSymbols, symbols: populatedSymbols,
wantMainSyms: []string{"main.main"}, wantMainSyms: []string{"main.main"},
wantDepSyms: []string{"github.com/foo/bar.Parse"}, wantDepSyms: []string{"github.com/foo/bar.Parse"},