github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/pkg/cataloger/golang/scan_binary.go (about) 1 package golang 2 3 import ( 4 "debug/buildinfo" 5 "fmt" 6 "io" 7 "runtime/debug" 8 9 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/internal/unionreader" 10 "github.com/nextlinux/gosbom/internal/log" 11 ) 12 13 // scanFile scans file to try to report the Go and module versions. 14 func scanFile(reader unionreader.UnionReader, filename string) ([]*debug.BuildInfo, []string) { 15 // NOTE: multiple readers are returned to cover universal binaries, which are files 16 // with more than one binary 17 readers, err := unionreader.GetReaders(reader) 18 if err != nil { 19 log.WithFields("error", err).Warnf("failed to open a golang binary") 20 return nil, nil 21 } 22 23 var builds []*debug.BuildInfo 24 for _, r := range readers { 25 bi, err := getBuildInfo(r) 26 if err != nil { 27 log.WithFields("file", filename, "error", err).Trace("unable to read golang buildinfo") 28 continue 29 } 30 if bi == nil { 31 continue 32 } 33 builds = append(builds, bi) 34 } 35 36 archs := getArchs(readers, builds) 37 38 return builds, archs 39 } 40 41 func getBuildInfo(r io.ReaderAt) (bi *debug.BuildInfo, err error) { 42 defer func() { 43 if r := recover(); r != nil { 44 // this can happen in cases where a malformed binary is passed in can be initially parsed, but not 45 // used without error later down the line. This is the case with : 46 // https://github.com/llvm/llvm-project/blob/llvmorg-15.0.6/llvm/test/Object/Inputs/macho-invalid-dysymtab-bad-size 47 err = fmt.Errorf("recovered from panic: %v", r) 48 } 49 }() 50 bi, err = buildinfo.Read(r) 51 52 // note: the stdlib does not export the error we need to check for 53 if err != nil { 54 if err.Error() == "not a Go executable" { 55 // since the cataloger can only select executables and not distinguish if they are a go-compiled 56 // binary, we should not show warnings/logs in this case. For this reason we nil-out err here. 57 err = nil 58 return 59 } 60 // in this case we could not read the or parse the file, but not explicitly because it is not a 61 // go-compiled binary (though it still might be). 62 return 63 } 64 return 65 }