• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SRC_MUTATOR_H_
16 #define SRC_MUTATOR_H_
17 
18 #include <stddef.h>
19 #include <stdint.h>
20 
21 #include <functional>
22 #include <memory>
23 #include <random>
24 #include <string>
25 #include <unordered_map>
26 #include <vector>
27 
28 #include "port/protobuf.h"
29 #include "src/random.h"
30 
31 namespace protobuf_mutator {
32 
33 // Randomly makes incremental change in the given protobuf.
34 // Usage example:
35 //    protobuf_mutator::Mutator mutator(1);
36 //    MyMessage message;
37 //    message.ParseFromString(encoded_message);
38 //    mutator.Mutate(&message, 10000);
39 //
40 // Class implements very basic mutations of fields. E.g. it just flips bits for
41 // integers, floats and strings. Also it increases, decreases size of
42 // strings only by one. For better results users should override
43 // protobuf_mutator::Mutator::Mutate* methods with more useful logic, e.g. using
44 // library like libFuzzer.
45 class Mutator {
46  public:
47   // seed: value to initialize random number generator.
48   Mutator() = default;
49   virtual ~Mutator() = default;
50 
51   // Initialized internal random number generator.
52   void Seed(uint32_t value);
53 
54   // message: message to mutate.
55   // max_size_hint: approximate max ByteSize() of resulting message. Method does
56   // not guarantee that real result will be strictly smaller than value. Caller
57   // could repeat mutation if result was larger than expected.
58   void Mutate(protobuf::Message* message, size_t max_size_hint);
59 
60   void CrossOver(const protobuf::Message& message1, protobuf::Message* message2,
61                  size_t max_size_hint);
62 
63   // Callback to postprocess mutations.
64   // Implementation should use seed to initialize random number generators.
65   using PostProcess =
66       std::function<void(protobuf::Message* message, unsigned int seed)>;
67 
68   // Register callback which will be called after every message mutation.
69   // In this callback fuzzer may adjust content of the message or mutate some
70   // fields in some fuzzer specific way.
71   void RegisterPostProcessor(const protobuf::Descriptor* desc,
72                              PostProcess callback);
73 
74  protected:
75   // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
76   virtual int32_t MutateInt32(int32_t value);
77   virtual int64_t MutateInt64(int64_t value);
78   virtual uint32_t MutateUInt32(uint32_t value);
79   virtual uint64_t MutateUInt64(uint64_t value);
80   virtual float MutateFloat(float value);
81   virtual double MutateDouble(double value);
82   virtual bool MutateBool(bool value);
83   virtual size_t MutateEnum(size_t index, size_t item_count);
84   virtual std::string MutateString(const std::string& value,
85                                    int size_increase_hint);
86 
random()87   RandomEngine* random() { return &random_; }
88 
89  private:
90   friend class FieldMutator;
91   friend class TestMutator;
92   bool MutateImpl(const std::vector<const protobuf::Message*>& sources,
93                   const std::vector<protobuf::Message*>& messages,
94                   bool copy_clone_only, int size_increase_hint);
95   std::string MutateUtf8String(const std::string& value,
96                                int size_increase_hint);
97   bool IsInitialized(const protobuf::Message& message) const;
98   bool keep_initialized_ = true;
99   size_t random_to_default_ratio_ = 100;
100   RandomEngine random_;
101   using PostProcessors =
102       std::unordered_multimap<const protobuf::Descriptor*, PostProcess>;
103   PostProcessors post_processors_;
104 };
105 
106 }  // namespace protobuf_mutator
107 
108 #endif  // SRC_MUTATOR_H_
109