github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go (about) 1 package dotnet 2 3 import ( 4 "fmt" 5 "io" 6 7 "github.com/saferwall/pe" 8 9 "github.com/anchore/packageurl-go" 10 "github.com/anchore/syft/internal/log" 11 "github.com/anchore/syft/syft/artifact" 12 "github.com/anchore/syft/syft/file" 13 "github.com/anchore/syft/syft/pkg" 14 "github.com/anchore/syft/syft/pkg/cataloger/generic" 15 ) 16 17 var _ generic.Parser = parseDotnetPortableExecutable 18 19 func parseDotnetPortableExecutable(_ file.Resolver, _ *generic.Environment, f file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { 20 by, err := io.ReadAll(f) 21 if err != nil { 22 return nil, nil, fmt.Errorf("unable to read file: %w", err) 23 } 24 25 peFile, err := pe.NewBytes(by, &pe.Options{}) 26 if err != nil { 27 return nil, nil, fmt.Errorf("unable to create PE file instance: %w", err) 28 } 29 30 err = peFile.Parse() 31 if err != nil { 32 return nil, nil, fmt.Errorf("unable to parse PE file: %w", err) 33 } 34 35 versionResources, err := peFile.ParseVersionResources() 36 if err != nil { 37 // this is not a fatal error, just log and continue 38 // TODO: consider this case for "known unknowns" (same goes for cases below) 39 log.Tracef("unable to parse version resources in PE file: %s", f.RealPath) 40 return nil, nil, nil 41 } 42 43 name := versionResources["FileDescription"] 44 if name == "" { 45 log.Tracef("unable to find FileDescription in PE file: %s", f.RealPath) 46 return nil, nil, nil 47 } 48 49 version := versionResources["FileVersion"] 50 if version == "" { 51 log.Tracef("unable to find FileVersion in PE file: %s", f.RealPath) 52 return nil, nil, nil 53 } 54 55 purl := packageurl.NewPackageURL( 56 packageurl.TypeNuget, // See explanation in syft/pkg/cataloger/dotnet/package.go as to why this was chosen. 57 "", 58 name, 59 version, 60 nil, 61 "", 62 ).ToString() 63 64 metadata := pkg.DotnetPortableExecutableMetadata{ 65 AssemblyVersion: versionResources["Assembly Version"], 66 LegalCopyright: versionResources["LegalCopyright"], 67 Comments: versionResources["Comments"], 68 InternalName: versionResources["InternalName"], 69 CompanyName: versionResources["CompanyName"], 70 ProductName: versionResources["ProductName"], 71 ProductVersion: versionResources["ProductVersion"], 72 } 73 74 p := pkg.Package{ 75 Name: name, 76 Version: version, 77 Locations: file.NewLocationSet(f.Location), 78 Type: pkg.DotnetPkg, 79 PURL: purl, 80 MetadataType: pkg.DotnetPortableExecutableMetadataType, 81 Metadata: metadata, 82 } 83 84 p.SetID() 85 86 return []pkg.Package{p}, nil, nil 87 }