diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go index 209ce2fb6..3ce5bc7ba 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go @@ -3,6 +3,8 @@ package dotnet import ( "fmt" "io" + "regexp" + "strings" "github.com/saferwall/pe" @@ -40,14 +42,14 @@ func parseDotnetPortableExecutable(_ file.Resolver, _ *generic.Environment, f fi return nil, nil, nil } - name := versionResources["FileDescription"] + name := findName(versionResources) if name == "" { - log.Tracef("unable to find FileDescription in PE file: %s", f.RealPath) + log.Tracef("unable to find FileDescription, or ProductName in PE file: %s", f.RealPath) return nil, nil, nil } - version := versionResources["FileVersion"] - if version == "" { + version := findVersion(versionResources) + if strings.TrimSpace(version) == "" { log.Tracef("unable to find FileVersion in PE file: %s", f.RealPath) return nil, nil, nil } @@ -84,3 +86,31 @@ func parseDotnetPortableExecutable(_ file.Resolver, _ *generic.Environment, f fi return []pkg.Package{p}, nil, nil } + +func findVersion(versionResources map[string]string) string { + for _, key := range []string{"FileVersion"} { + if version, ok := versionResources[key]; ok { + if strings.TrimSpace(version) == "" { + continue + } + fields := strings.Fields(version) + if len(fields) > 0 { + return fields[0] + } + } + } + return "" +} + +func findName(versionResources map[string]string) string { + for _, key := range []string{"FileDescription", "ProductName"} { + if name, ok := versionResources[key]; ok { + if strings.TrimSpace(name) == "" { + continue + } + trimmed := strings.TrimSpace(name) + return regexp.MustCompile(`[^a-zA-Z0-9.]+`).ReplaceAllString(trimmed, "") + } + } + return "" +} diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go index 979724d3a..6bdf41dcb 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go @@ -10,28 +10,74 @@ import ( ) func TestParseDotnetPortableExecutable(t *testing.T) { - fixture := "test-fixtures/System.Buffers.dll" - fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) - - expected := []pkg.Package{ + tests := []struct { + fixture string + expected []pkg.Package + }{ { - Name: "System.Buffers", - Version: "7.0.923.36201", - Locations: fixtureLocationSet, - Type: pkg.DotnetPkg, - PURL: "pkg:nuget/System.Buffers@7.0.923.36201", - Metadata: pkg.DotnetPortableExecutableEntry{ - AssemblyVersion: "7.0.0.0", - LegalCopyright: "© Microsoft Corporation. All rights reserved.", - Comments: "System.Buffers", - InternalName: "System.Buffers.dll", - CompanyName: "Microsoft Corporation", - ProductName: "Microsoft® .NET", - ProductVersion: "7.0.9+8e9a17b2216f51a5788f8b1c467a4cf3b769e7d7", + fixture: "test-fixtures/System.Buffers.dll", + expected: []pkg.Package{ + { + Name: "System.Buffers", + Version: "7.0.923.36201", + Type: pkg.DotnetPkg, + PURL: "pkg:nuget/System.Buffers@7.0.923.36201", + Metadata: pkg.DotnetPortableExecutableEntry{ + AssemblyVersion: "7.0.0.0", + LegalCopyright: "© Microsoft Corporation. All rights reserved.", + Comments: "System.Buffers", + InternalName: "System.Buffers.dll", + CompanyName: "Microsoft Corporation", + ProductName: "Microsoft® .NET", + ProductVersion: "7.0.9+8e9a17b2216f51a5788f8b1c467a4cf3b769e7d7", + }, + }, + }, + }, + { + fixture: "test-fixtures/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + expected: []pkg.Package{ + { + Name: "ActiveDirectoryAuthenticationLibrary", + Version: "3.14.40721.0918", + Type: pkg.DotnetPkg, + PURL: "pkg:nuget/ActiveDirectoryAuthenticationLibrary@3.14.40721.0918", + Metadata: pkg.DotnetPortableExecutableEntry{ + AssemblyVersion: "3.14.2.11", + LegalCopyright: "Copyright (c) Microsoft Corporation. All rights reserved.", + InternalName: "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + CompanyName: "Microsoft Corporation", + ProductName: "Active Directory Authentication Library", + ProductVersion: "c61f043686a544863efc014114c42e844f905336", + }, + }, + }, + }, + { + fixture: "test-fixtures/sni.dll", + expected: []pkg.Package{ + { + Name: "bFileVersion", + Version: "4.6.25512.01", + Type: pkg.DotnetPkg, + PURL: "pkg:nuget/bFileVersion@4.6.25512.01", + Metadata: pkg.DotnetPortableExecutableEntry{ + LegalCopyright: "© Microsoft Corporation. All rights reserved.", + CompanyName: "Microsoft Corporation", + ProductName: "Microsoft® .NET Framework", + ProductVersion: "4.6.25512.01 built by: dlab-DDVSOWINAGE016. Commit Hash: d0d5c7b49271cadb6d97de26d8e623e98abdc8db", + }, + }, }, }, } - var expectedRelationships []artifact.Relationship - pkgtest.TestFileParser(t, fixture, parseDotnetPortableExecutable, expected, expectedRelationships) + for _, tc := range tests { + t.Run(tc.fixture, func(t *testing.T) { + fixtureLocationSet := file.NewLocationSet(file.NewLocation(tc.fixture)) + tc.expected[0].Locations = fixtureLocationSet + var expectedRelationships []artifact.Relationship + pkgtest.TestFileParser(t, tc.fixture, parseDotnetPortableExecutable, tc.expected, expectedRelationships) + }) + } }