// CheckStdlib checks the standard library.
//
// This constructs a synthetic package configuration for each library in the
// standard library sources, and call CheckPackage repeatedly.
//
// Note that not all parts of the source are expected to build. We skip obvious
// test files, and cmd files, which should not be dependencies.
CheckStdlib checks the standard library.

This constructs a synthetic package configuration for each library in the
standard library sources, and call CheckPackage repeatedly.

Note that not all parts of the source are expected to build. We skip obvious
test files, and cmd files, which should not be dependencies.
// CheckStdlib checks the standard library . // // This constructs a synthetic package configuration for each library in the // standard library sources and call CheckPackage repeatedly . // // Note that not all parts of the source are expected to build . We skip obvious // test files and cmd files which should not be dependencies .
func CheckStdlib(config *StdlibConfig, analyzers []*analysis.Analyzer) (allFindings FindingSet, facts []byte, err error) {
	if len(config.Srcs) == 0 {
		return nil, nil, nil
	}
	for i := 0; i < len(config.Srcs); i++ {
		config.Srcs[i] = path.Clean(config.Srcs[i])
	}
	 Note that there may be extra files outside of the root source
	 directory; we simply ignore those.
	rootSrcPrefix := ""
	for _, file := range config.Srcs {
		const src = "/src/"
		i := strings.Index(file, src)
		if i == -1 {
			 Superfluous file.
			continue
		}
		 Index of first character after /src/.
		i += len(src)
		rootSrcPrefix = file[:i]
		break
	}
	 Aggregate all files by directory.
	packages := make(map[string]*PackageConfig)
	for _, file := range config.Srcs {
		if !strings.HasPrefix(file, rootSrcPrefix) {
			 Superflouous file.
			continue
		}
		d := path.Dir(file)
		if len(rootSrcPrefix) >= len(d) {
			continue  Not a file.
		}
		pkg := d[len(rootSrcPrefix):]
		 Skip cmd packages and obvious test files: see above.
		if strings.HasPrefix(pkg, "cmd/") || strings.HasSuffix(file, "_test.go") {
			continue
		}
		c, ok := packages[pkg]
		if !ok {
			c = &PackageConfig{
				ImportPath: pkg,
				GOOS:       config.GOOS,
				GOARCH:     config.GOARCH,
				Tags:       config.Tags,
			}
			packages[pkg] = c
		}
		 Add the files appropriately. Note that they will be further
		 filtered by architecture and build tags below, so this need
		 not be done immediately.
		if strings.HasSuffix(file, ".go") {
			c.GoFiles = append(c.GoFiles, file)
		} else {
			c.NonGoFiles = append(c.NonGoFiles, file)
		}
	}
	 Closure to check a single package.
	localStdlibFacts := make(stdlibFacts)
	localStdlibErrs := make(map[string]error)
	var checkOne func(pkg string) error  Recursive.
	checkOne = func(pkg string) error {
		 Is this already done?
		if _, ok := localStdlibFacts[pkg]; ok {
			return nil
		}
		 Did this fail previously?
		if _, ok := localStdlibErrs[pkg]; ok {
			return nil
		}
		 Lookup the configuration.
		config, ok := packages[pkg]
		if !ok {
			return nil  Not known.
		}
		 Find the binary package, and provide to objdump.
		rc, err := findStdPkg(config.GOOS, config.GOARCH, pkg)
		if err != nil {
			 If there's no binary for this package, it is likely
			 not built with the distribution. That's fine, we can
			 just skip analysis.
			localStdlibErrs[pkg] = err
			return nil
		}
		 Provide the input.
		oldReader := checkescape.Reader
		checkescape.Reader = rc  For analysis.
		defer func() {
			rc.Close()
			checkescape.Reader = oldReader  Restore.
		}()
		 Run the analysis.
		findings, factData, err := CheckPackage(config, analyzers, checkOne)
		if err != nil {
			 If we can't analyze a package from the standard library,
			 then we skip it. It will simply not have any findings.
			localStdlibErrs[pkg] = err
			return nil
		}
		localStdlibFacts[pkg] = factData
		allFindings = append(allFindings, findings...)
		return nil
	}
	 Check all packages.
	 Note that this may call checkOne recursively, so it's not guaranteed
	 to evaluate in the order provided here. We do ensure however, that
	 all packages are evaluated.
	for pkg := range packages {
		if err := checkOne(pkg); err != nil {
			return nil, nil, err
		}
	}
	 Sanity check.
	if len(localStdlibFacts) == 0 {
		return nil, nil, fmt.Errorf("no stdlib facts found: misconfiguration?")
	}
	 Write out all findings.
	buf := bytes.NewBuffer(nil)
	if err := localStdlibFacts.EncodeTo(buf); err != nil {
		return nil, nil, fmt.Errorf("error serialized stdlib facts: %v", err)
	}
	 Write out all errors.
	for pkg, err := range localStdlibErrs {
		log.Printf("WARNING: error while processing %v: %v", pkg, err)
	}
	 Return all findings.
	return allFindings, buf.Bytes(), nil
}
func CheckStdlib ( config * StdlibConfig , analyzers [ ] * analysis . Analyzer ) ( allFindings FindingSet , facts [ ] byte , err error ) { if len ( config . Srcs ) == 0 { return nil , nil , nil } for i := 0 ; i < len ( config . Srcs ) ; i ++ { config . Srcs [ i ] = path . Clean ( config . Srcs [ i ] ) } rootSrcPrefix := " " for _ , file := range config . Srcs { const src = " " i := strings . Index ( file , src ) if i == - 1 { continue } i += len ( src ) rootSrcPrefix = file [ : i ] break } packages := make ( map [ string ] * PackageConfig ) for _ , file := range config . Srcs { if ! strings . HasPrefix ( file , rootSrcPrefix ) { continue } d := path . Dir ( file ) if len ( rootSrcPrefix ) >= len ( d ) { continue } pkg := d [ len ( rootSrcPrefix ) : ] if strings . HasPrefix ( pkg , " " ) || strings . HasSuffix ( file , " " ) { continue } c , ok := packages [ pkg ] if ! ok { c = & PackageConfig { ImportPath : pkg , GOOS : config . GOOS , GOARCH : config . GOARCH , Tags : config . Tags , } packages [ pkg ] = c } if strings . HasSuffix ( file , " " ) { c . GoFiles = append ( c . GoFiles , file ) } else { c . NonGoFiles = append ( c . NonGoFiles , file ) } } localStdlibFacts := make ( stdlibFacts ) localStdlibErrs := make ( map [ string ] error ) var checkOne func ( pkg string ) error checkOne = func ( pkg string ) error { if _ , ok := localStdlibFacts [ pkg ] ; ok { return nil } if _ , ok := localStdlibErrs [ pkg ] ; ok { return nil } config , ok := packages [ pkg ] if ! ok { return nil } rc , err := findStdPkg ( config . GOOS , config . GOARCH , pkg ) if err != nil { localStdlibErrs [ pkg ] = err return nil } oldReader := checkescape . Reader checkescape . Reader = rc defer func ( ) { rc . Close ( ) checkescape . Reader = oldReader } ( ) findings , factData , err := CheckPackage ( config , analyzers , checkOne ) if err != nil { localStdlibErrs [ pkg ] = err return nil } localStdlibFacts [ pkg ] = factData allFindings = append ( allFindings , findings ... ) return nil } for pkg := range packages { if err := checkOne ( pkg ) ; err != nil { return nil , nil , err } } if len ( localStdlibFacts ) == 0 { return nil , nil , fmt . Errorf ( " " ) } buf := bytes . NewBuffer ( nil ) if err := localStdlibFacts . EncodeTo ( buf ) ; err != nil { return nil , nil , fmt . Errorf ( " " , err ) } for pkg , err := range localStdlibErrs { log . Printf ( " " , pkg , err ) } return allFindings , buf . Bytes ( ) , nil }
CheckStdlib checks the standard library.
CheckStdlib checks the standard library .
// Ensure all paths are normalized. // Calculate the root source directory. This is always a directory // named 'src', of which we simply take the first we find. This is a // bit fragile, but works for all currently known Go source // configurations. // // Note that there may be extra files outside of the root source // directory; we simply ignore those. // Superfluous file. // Index of first character after /src/. // Aggregate all files by directory. // Superflouous file. // Not a file. // Skip cmd packages and obvious test files: see above. // Add the files appropriately. Note that they will be further // filtered by architecture and build tags below, so this need // not be done immediately. // Closure to check a single package. // Recursive. // Is this already done? // Did this fail previously? // Lookup the configuration. // Not known. // Find the binary package, and provide to objdump. // If there's no binary for this package, it is likely // not built with the distribution. That's fine, we can // just skip analysis. // Provide the input. // For analysis. // Restore. // Run the analysis. // If we can't analyze a package from the standard library, // then we skip it. It will simply not have any findings. // Check all packages. // // Note that this may call checkOne recursively, so it's not guaranteed // to evaluate in the order provided here. We do ensure however, that // all packages are evaluated. // Sanity check. // Write out all findings. // Write out all errors. // Return all findings.