@@ -40,6 +40,7 @@ import (
4040type DiffFuzzerConfig struct {
4141 Debug bool
4242 PatchedOnly chan * UniqueBug
43+ BaseCrashes chan string
4344 Store * DiffFuzzerStore
4445 ArtifactsDir string // Where to store the artifacts that supplement the logs.
4546 // The fuzzer waits no more than MaxTriageTime time until it starts taking VMs away
@@ -51,6 +52,11 @@ type DiffFuzzerConfig struct {
5152 // trying to reach the modified code. The time is counted since the moment
5253 // 99% of the corpus is triaged.
5354 FuzzToReachPatched time.Duration
55+ // The callback may be used to consult external systems on whether the
56+ // base kernel has ever crashed with the given title.
57+ // It may help reduce the false positive rate and prevent unnecessary
58+ // bug reproductions.
59+ BaseCrashKnown func (context.Context , string ) (bool , error )
5460}
5561
5662func (cfg * DiffFuzzerConfig ) TriageDeadline () <- chan time.Time {
@@ -186,13 +192,13 @@ loop:
186192 log .Logf (0 , "STAT %s" , data )
187193 case rep := <- dc .base .crashes :
188194 log .Logf (1 , "base crash: %v" , rep .Title )
189- dc .store . BaseCrashed ( rep . Title , rep . Report )
195+ dc .reportBaseCrash ( ctx , rep )
190196 case ret := <- runner .done :
191197 // We have run the reproducer on the base instance.
192198
193199 // A sanity check: the base kernel might have crashed with the same title
194200 // since the moment we have stared the reproduction / running on the repro base.
195- crashesOnBase := dc .store . EverCrashedBase ( ret .origReport .Title )
201+ crashesOnBase := dc .everCrashedBase ( ctx , ret .origReport .Title )
196202 if ret .crashReport == nil && crashesOnBase {
197203 // Report it as error so that we could at least find it in the logs.
198204 log .Errorf ("repro didn't crash base, but base itself crashed: %s" , ret .origReport .Title )
@@ -218,7 +224,7 @@ loop:
218224 })
219225 }
220226 } else {
221- dc .store . BaseCrashed ( ret . origReport . Title , ret .origReport . Report )
227+ dc .reportBaseCrash ( ctx , ret .origReport )
222228 log .Logf (0 , "crashes both: %s / %s" , ret .origReport .Title , ret .crashReport .Title )
223229 }
224230 case ret := <- dc .doneRepro :
@@ -254,6 +260,36 @@ loop:
254260 return g .Wait ()
255261}
256262
263+ func (dc * diffContext ) everCrashedBase (ctx context.Context , title string ) bool {
264+ if dc .store .EverCrashedBase (title ) {
265+ return true
266+ }
267+ // Let's try to ask the external systems about it as well.
268+ if dc .cfg .BaseCrashKnown != nil {
269+ known , err := dc .cfg .BaseCrashKnown (ctx , title )
270+ if err != nil {
271+ log .Logf (0 , "a call to BaseCrashKnown failed: %v" , err )
272+ } else {
273+ if known {
274+ log .Logf (0 , "base crash %q is already known" , title )
275+ }
276+ return known
277+ }
278+ }
279+ return false
280+ }
281+
282+ func (dc * diffContext ) reportBaseCrash (ctx context.Context , rep * report.Report ) {
283+ dc .store .BaseCrashed (rep .Title , rep .Report )
284+ if dc .cfg .BaseCrashes == nil {
285+ return
286+ }
287+ select {
288+ case dc .cfg .BaseCrashes <- rep .Title :
289+ case <- ctx .Done ():
290+ }
291+ }
292+
257293func (dc * diffContext ) waitCorpusTriage (ctx context.Context , threshold float64 ) chan struct {} {
258294 const backOffTime = 30 * time .Second
259295 ret := make (chan struct {})
@@ -343,7 +379,10 @@ func (dc *diffContext) NeedRepro(crash *Crash) bool {
343379 }
344380 dc .mu .Lock ()
345381 defer dc .mu .Unlock ()
346- if dc .store .EverCrashedBase (crash .Title ) {
382+
383+ ctx , cancel := context .WithTimeout (context .Background (), time .Minute )
384+ defer cancel ()
385+ if dc .everCrashedBase (ctx , crash .Title ) {
347386 return false
348387 }
349388 if dc .reproAttempts [crash .Title ] > maxReproAttempts {
0 commit comments