[libFuzzer] Fallback to default Mutate when MutateWithMask fails.
authorMax Moroz <mmoroz@chromium.org>
Thu, 11 Apr 2019 16:24:53 +0000 (16:24 +0000)
committerMax Moroz <mmoroz@chromium.org>
Thu, 11 Apr 2019 16:24:53 +0000 (16:24 +0000)
Summary:
In case the current corpus input doesn't have bytes going into the
focus function, MutateWithMask is useless and may fail gently, allowing the
default mutation routine happen, rather than crashing on an assertion.

For more context and the initial fix suggestion, see:
https://github.com/google/oss-fuzz/issues/1632#issuecomment-481862879

Reviewers: kcc, morehouse

Reviewed By: kcc

Subscribers: delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

Differential Revision: https://reviews.llvm.org/D60567

llvm-svn: 358190

compiler-rt/lib/fuzzer/FuzzerLoop.cpp
compiler-rt/lib/fuzzer/FuzzerMutate.cpp

index b86512b..40461c2 100644 (file)
@@ -658,7 +658,9 @@ void Fuzzer::MutateAndTestOne() {
         Size <= CurrentMaxMutationLen)
       NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size,
                                   II.DataFlowTraceForFocusFunction);
-    else
+    
+    // If MutateWithMask either failed or wasn't called, call default Mutate.
+    if (!NewSize)
       NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
     assert(NewSize > 0 && "Mutator returned empty unit");
     assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
index 92e469f..a825b83 100644 (file)
@@ -542,6 +542,7 @@ size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
     if (Mask[I])
       T[OneBits++] = Data[I];
 
+  if (!OneBits) return 0;
   assert(!T.empty());
   size_t NewSize = Mutate(T.data(), OneBits, OneBits);
   assert(NewSize <= OneBits);