func processAll()

in cmd/cpe2cve/cpe2cve.go [37:120]


func processAll(in <-chan []string, out chan<- []string, caches map[string]*cvefeed.Cache, cfg config, nlines *uint64) {
	cpesAt := cfg.CPEsAt - 1
	for rec := range in {
		if cpesAt >= len(rec) {
			flog.Errorf("not enough fields in input (%d)", len(rec))
			continue
		}
		if stats.AreLogged() {
			stats.IncrementCounter("line.total")
		}
		cpeList := strings.Split(rec[cpesAt], cfg.InRecordSeparator)
		cpes := make([]*wfn.Attributes, 0, len(cpeList))
		for _, uri := range cpeList {
			if stats.AreLogged() {
				stats.IncrementCounter("cpe.total")
			}
			attr, err := wfn.Parse(uri)
			if err != nil {
				flog.Errorf("couldn't parse uri %q: %v", uri, err)
				continue
			}
			cpes = append(cpes, attr)
		}
		rec[cpesAt] = strings.Join(cpeList, cfg.OutRecordSeparator)

		// if performance seems to be the issue, we could try to make these cache.Get's concurrent:
		//
		// wg := sync.WaitGroup{}
		// for provider, cache := range caches {
		// 	provider, cache := provider, cache
		// 	wg.Add(1)
		// 	go func() {
		// 		defer wg.Done()
		// 		for _, matches := range cache.Get(cpes) {
		// ...
		for provider, cache := range caches {
			for _, matches := range cache.Get(cpes) {
				ml := len(matches.CPEs)
				if stats.AreLogged() {
					stats.IncrementCounterBy("cpe.match", int64(ml))
					if ml != 0 {
						stats.IncrementCounter("line.match")
					}
				}
				matchingCPEs := make([]string, ml)
				for i, attr := range matches.CPEs {
					if attr == nil {
						flog.Errorf("%s matches nil CPE", matches.CVE.ID())
						continue
					}
					matchingCPEs[i] = (*wfn.Attributes)(attr).BindToURI()
				}
				rec2 := make([]string, len(rec))
				copy(rec2, rec)
				cvss := matches.CVE.CVSSv3BaseScore()
				if cvss == 0 {
					cvss = matches.CVE.CVSSv2BaseScore()
				}
				rec2 = cfg.EraseFields.appendAt(
					rec2,
					cfg.CVEsAt-1, matches.CVE.ID(),
					cfg.MatchesAt-1, strings.Join(matchingCPEs, cfg.OutRecordSeparator),
					cfg.CWEsAt-1, strings.Join(matches.CVE.CWEs(), cfg.OutRecordSeparator),
					cfg.CVSS2At-1, fmt.Sprintf("%.1f", matches.CVE.CVSSv2BaseScore()),
					cfg.CVSS3At-1, fmt.Sprintf("%.1f", matches.CVE.CVSSv3BaseScore()),
					cfg.CVSSAt-1, fmt.Sprintf("%.1f", cvss),
					cfg.ProviderAt-1, provider,
				)
				out <- rec2
			}
		}

		n := atomic.AddUint64(nlines, 1)
		if n > 0 {
			if n%10000 == 0 {
				flog.V(1).Infoln(n, "lines processed")
			} else if n%1000 == 0 {
				flog.V(2).Infoln(n, "lines processed")
			} else if n%100 == 0 {
				flog.V(3).Infoln(n, "lines processed")
			}
		}
	}
}