func triageInput(env *ipc.Env, inp Input) { if *flagNoCover { panic("should not be called when coverage is disabled") } call := inp.p.Calls[inp.call].Meta newCover := cover.Difference(inp.cover, corpusCover[call.CallID]) newCover = cover.Difference(newCover, flakes) if len(newCover) == 0 { return } if _, ok := corpusHashes[hash(inp.p.Serialize())]; ok { return } minCover := inp.cover for i := 0; i < 3; i++ { allCover := execute1(env, inp.p, &statExecTriage) if len(allCover[inp.call]) == 0 { // The call was not executed. Happens sometimes, reason unknown. continue } cov := allCover[inp.call] diff := cover.SymmetricDifference(inp.cover, cov) if len(diff) != 0 { flakes = cover.Union(flakes, diff) } minCover = cover.Intersection(minCover, cov) } stableNewCover := cover.Intersection(newCover, minCover) if len(stableNewCover) == 0 { return } inp.p, inp.call = prog.Minimize(inp.p, inp.call, func(p1 *prog.Prog, call1 int) bool { allCover := execute1(env, p1, &statExecMinimize) if len(allCover[call1]) == 0 { return false // The call was not executed. } cov := allCover[call1] if len(cover.Intersection(stableNewCover, cov)) != len(stableNewCover) { return false } minCover = cover.Intersection(minCover, cov) return true }) inp.cover = minCover corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], minCover) corpus = append(corpus, inp) data := inp.p.Serialize() corpusHashes[hash(data)] = struct{}{} logf(2, "added new input for %v to corpus:\n%s", call.CallName, data) statNewInput++ a := &NewManagerInputArgs{*flagName, RpcInput{call.CallName, inp.p.Serialize(), inp.call, []uint32(inp.cover)}} if err := manager.Call("Manager.NewInput", a, nil); err != nil { panic(err) } }
func triageInput(pid int, env *ipc.Env, inp Input) { if noCover { panic("should not be called when coverage is disabled") } call := inp.p.Calls[inp.call].Meta coverMu.RLock() newCover := cover.Difference(inp.cover, corpusCover[call.CallID]) newCover = cover.Difference(newCover, flakes) coverMu.RUnlock() if len(newCover) == 0 { return } corpusMu.RLock() if _, ok := corpusHashes[hash(inp.p.Serialize())]; ok { corpusMu.RUnlock() return } corpusMu.RUnlock() minCover := inp.cover for i := 0; i < 3; i++ { allCover := execute1(pid, env, inp.p, &statExecTriage) if len(allCover[inp.call]) == 0 { // The call was not executed. Happens sometimes, reason unknown. continue } coverMu.RLock() cov := allCover[inp.call] diff := cover.SymmetricDifference(inp.cover, cov) minCover = cover.Intersection(minCover, cov) updateFlakes := len(diff) != 0 && len(cover.Difference(diff, flakes)) != 0 coverMu.RUnlock() if updateFlakes { coverMu.Lock() flakes = cover.Union(flakes, diff) coverMu.Unlock() } } stableNewCover := cover.Intersection(newCover, minCover) if len(stableNewCover) == 0 { return } inp.p, inp.call = prog.Minimize(inp.p, inp.call, func(p1 *prog.Prog, call1 int) bool { allCover := execute1(pid, env, p1, &statExecMinimize) coverMu.RLock() defer coverMu.RUnlock() if len(allCover[call1]) == 0 { return false // The call was not executed. } cov := allCover[call1] if len(cover.Intersection(stableNewCover, cov)) != len(stableNewCover) { return false } minCover = cover.Intersection(minCover, cov) return true }, false) inp.cover = minCover atomic.AddUint64(&statNewInput, 1) data := inp.p.Serialize() Logf(2, "added new input for %v to corpus:\n%s", call.CallName, data) a := &NewInputArgs{*flagName, RpcInput{call.CallName, data, inp.call, []uint32(inp.cover)}} if err := manager.Call("Manager.NewInput", a, nil); err != nil { panic(err) } corpusMu.Lock() defer corpusMu.Unlock() coverMu.Lock() defer coverMu.Unlock() corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], minCover) corpus = append(corpus, inp.p) corpusHashes[hash(data)] = struct{}{} }