Snap for 6183524 from abe19d4f77fd2f0fc9c5dd6b8283d692fa3a3c4c to r-keystone-qcom-release

Change-Id: I136a8a7b453e50fef02e9b65dee913e84bdfa101
diff --git a/METADATA b/METADATA
index 975ee06..26788ce 100644
--- a/METADATA
+++ b/METADATA
@@ -5,11 +5,11 @@
     type: GIT
     value: "https://github.com/google/libprotobuf-mutator"
   }
-  version: "62c5c91a2bfd675fa99cf61f6747fd227da8983a"
+  version: "69d93082200bb657f6db9c6b07b71bb94ea7bb47"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2019
-    month: 9
-    day: 28
+    year: 2020
+    month: 1
+    day: 8
   }
 }
diff --git a/README.md b/README.md
index 02683cd..842214e 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,29 @@
 
 Please see [libfuzzer_example.cc](/examples/libfuzzer/libfuzzer_example.cc) as an example.
 
+### Mutation post-processing (experimental)
+Sometimes it's necessary to keep particular values in some fields without which the proto
+is going to be rejected by fuzzed code. E.g. code may expect consistency between some fields
+or it may use some fields as checksums. Such constraints are going to be significant bottleneck
+for fuzzer even if it's capable of inserting acceptable values with time.
+
+PostProcessorRegistration can be used to avoid such issue and guide your fuzzer towards interesing
+code. It registers callback which will be called for each message of particular type after each mutation.
+
+```
+DEFINE_PROTO_FUZZER(const MyMessageType& input) {
+  static PostProcessorRegistration reg = {
+      [](MyMessageType* message, unsigned int seed) {
+        TweakMyMessageType(message, seed);
+      }};
+
+  // Code which needs to be fuzzed.
+  ConsumeMyMessageType(input);
+}
+```
+
+Optional: Use seed if callback uses random numbers. It may help later with debugging.
+
 ## UTF-8 strings
 "proto2" and "proto3" handle invalid UTF-8 strings differently. In both cases
 string should be UTF-8, however only "proto3" enforces that. So if fuzzer is
diff --git a/src/libfuzzer/libfuzzer_macro.cc b/src/libfuzzer/libfuzzer_macro.cc
index 5f9023f..c37276d 100644
--- a/src/libfuzzer/libfuzzer_macro.cc
+++ b/src/libfuzzer/libfuzzer_macro.cc
@@ -184,10 +184,11 @@
                 : ParseTextMessage(data, size, input);
 }
 
-void RegisterPostProcessorImpl(
+void RegisterPostProcessor(
+    const protobuf::Descriptor* desc,
     std::function<void(protobuf::Message* message, unsigned int seed)>
         callback) {
-  GetMutator()->RegisterPostProcessor(callback);
+  GetMutator()->RegisterPostProcessor(desc, callback);
 }
 
 }  // namespace libfuzzer
diff --git a/src/libfuzzer/libfuzzer_macro.h b/src/libfuzzer/libfuzzer_macro.h
index a7d26ab..1a1fe0a 100644
--- a/src/libfuzzer/libfuzzer_macro.h
+++ b/src/libfuzzer/libfuzzer_macro.h
@@ -106,7 +106,8 @@
 bool LoadProtoInput(bool binary, const uint8_t* data, size_t size,
                     protobuf::Message* input);
 
-void RegisterPostProcessorImpl(
+void RegisterPostProcessor(
+    const protobuf::Descriptor* desc,
     std::function<void(protobuf::Message* message, unsigned int seed)>
         callback);
 
@@ -114,9 +115,9 @@
 struct PostProcessorRegistration {
   PostProcessorRegistration(
       const std::function<void(Proto* message, unsigned int seed)>& callback) {
-    protobuf_mutator::libfuzzer::RegisterPostProcessorImpl(
-        [callback](protobuf_mutator::protobuf::Message* message,
-                   unsigned int seed) {
+    RegisterPostProcessor(
+        Proto::descriptor(),
+        [callback](protobuf::Message* message, unsigned int seed) {
           callback(static_cast<Proto*>(message), seed);
         });
   }
diff --git a/src/mutator.cc b/src/mutator.cc
index e3c9b39..e4e0305 100644
--- a/src/mutator.cc
+++ b/src/mutator.cc
@@ -457,7 +457,43 @@
   InitializeAndTrim(message, kMaxInitializeDepth);
   assert(!keep_initialized_ || message->IsInitialized());
 
-  if (post_process_) post_process_(message, random_());
+  if (!post_processors_.empty()) {
+    ApplyPostProcessing(message);
+  }
+}
+
+void Mutator::RegisterPostProcessor(const protobuf::Descriptor* desc,
+                                    PostProcess callback) {
+  post_processors_.emplace(desc, callback);
+}
+
+void Mutator::ApplyPostProcessing(Message* message) {
+  const Descriptor* descriptor = message->GetDescriptor();
+
+  auto it = post_processors_.find(descriptor);
+  if (it != post_processors_.end()) {
+    it->second(message, random_());
+  }
+
+  // Now recursively apply custom mutators.
+  const Reflection* reflection = message->GetReflection();
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    const FieldDescriptor* field = descriptor->field(i);
+    if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+      continue;
+    }
+    if (field->is_repeated()) {
+      const int field_size = reflection->FieldSize(*message, field);
+      for (int j = 0; j < field_size; ++j) {
+        Message* nested_message =
+            reflection->MutableRepeatedMessage(message, field, j);
+        ApplyPostProcessing(nested_message);
+      }
+    } else if (reflection->HasField(*message, field)) {
+      Message* nested_message = reflection->MutableMessage(message, field);
+      ApplyPostProcessing(nested_message);
+    }
+  }
 }
 
 void Mutator::MutateImpl(Message* message, size_t size_increase_hint) {
@@ -500,7 +536,9 @@
   InitializeAndTrim(message2, kMaxInitializeDepth);
   assert(!keep_initialized_ || message2->IsInitialized());
 
-  if (post_process_) post_process_(message2, random_());
+  if (!post_processors_.empty()) {
+    ApplyPostProcessing(message2);
+  }
 
   // Can't call mutate from crossover because of a bug in libFuzzer.
   // if (MessageDifferencer::Equals(*message2_copy, *message2) ||
@@ -582,11 +620,6 @@
   }
 }
 
-void Mutator::RegisterPostProcessor(PostProcess post_process) {
-  assert(!post_process_);
-  post_process_ = post_process;
-}
-
 void Mutator::InitializeAndTrim(Message* message, int max_depth) {
   const Descriptor* descriptor = message->GetDescriptor();
   const Reflection* reflection = message->GetReflection();
diff --git a/src/mutator.h b/src/mutator.h
index 73e1966..7af7b38 100644
--- a/src/mutator.h
+++ b/src/mutator.h
@@ -70,7 +70,8 @@
   // Register callback which will be called after every message mutation.
   // In this callback fuzzer may adjust content of the message or mutate some
   // fields in some fuzzer specific way.
-  void RegisterPostProcessor(PostProcess post_process);
+  void RegisterPostProcessor(const protobuf::Descriptor* desc,
+                             PostProcess callback);
 
  protected:
   // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
@@ -85,6 +86,8 @@
   virtual std::string MutateString(const std::string& value,
                                    size_t size_increase_hint);
 
+  std::unordered_map<const protobuf::Descriptor*, PostProcess> post_processors_;
+
   RandomEngine* random() { return &random_; }
 
  private:
@@ -96,12 +99,10 @@
                      protobuf::Message* message2);
   std::string MutateUtf8String(const std::string& value,
                                size_t size_increase_hint);
-  bool ApplyCustomMutations(protobuf::Message* message,
-                            const protobuf::FieldDescriptor* field);
+  void ApplyPostProcessing(protobuf::Message* message);
   bool keep_initialized_ = true;
   size_t random_to_default_ratio_ = 100;
   RandomEngine random_;
-  PostProcess post_process_;
 };
 
 }  // namespace protobuf_mutator
diff --git a/src/mutator_test.cc b/src/mutator_test.cc
index 0ae37aa..a86760a 100644
--- a/src/mutator_test.cc
+++ b/src/mutator_test.cc
@@ -593,7 +593,8 @@
 
   TestMutator mutator(false);
   mutator.RegisterPostProcessor(
-      [kIndicatorString](protobuf::Message* message, uint32_t seed) {
+      TestFixture::Message::descriptor(),
+      [kIndicatorString](protobuf::Message* message, unsigned int seed) {
         typename TestFixture::Message* test_message =
             static_cast<typename TestFixture::Message*>(message);
         if (seed % 2) test_message->set_optional_string(kIndicatorString);