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")
}
}
}
}