From 2bcf1c0373195724161a9dc287e1dbc26404e4fa Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 29 Oct 2021 11:21:45 -0700 Subject: [PATCH] internal/fuzz: don't add duplicate corpus entries If a identical input is already present in the corpus, don't re-add it. This may happen when the same input produces a different coverage map, causing the coordinator to think it has found a new input. This fixes a race between reading/writing cached inputs. Fixes #48721 Change-Id: I4807602f433c2b99396d25ceaa58b827796b3555 Reviewed-on: https://go-review.googlesource.com/c/go/+/359755 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 5008927f0e..78319a7496 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -316,6 +316,23 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Update the coordinator's coverage mask and save the value. inputSize := len(result.entry.Data) if opts.CacheDir != "" { + // It is possible that the input that was discovered is already + // present in the corpus, but the worker produced a coverage map + // that still expanded our total coverage (this may happen due to + // flakiness in the coverage counters). In order to prevent adding + // duplicate entries to the corpus (and re-writing the file on + // disk), skip it if the on disk file already exists. + // TOOD(roland): this check is limited in that it will only be + // applied if we are using the CacheDir. Another option would be + // to iterate through the corpus and check if it is already present, + // which would catch cases where we are not caching entries. + // A slightly faster approach would be to keep some kind of map of + // entry hashes, which would allow us to avoid iterating through + // all entries. + _, err = os.Stat(result.entry.Path) + if err == nil { + continue + } err := writeToCorpus(&result.entry, opts.CacheDir) if err != nil { stop(err) -- 2.50.0