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 <memory>
22 #include <random>
23 #include <string>
24 
25 #include "port/protobuf.h"
26 #include "src/random.h"
27 
28 namespace protobuf_mutator {
29 
30 // Randomly makes incremental change in the given protobuf.
31 // Usage example:
32 //    protobuf_mutator::Mutator mutator(1);
33 //    MyMessage message;
34 //    message.ParseFromString(encoded_message);
35 //    mutator.Mutate(&message, 10000);
36 //
37 // Class implements very basic mutations of fields. E.g. it just flips bits for
38 // integers, floats and strings. Also it increases, decreases size of
39 // strings only by one. For better results users should override
40 // protobuf_mutator::Mutator::Mutate* methods with more useful logic, e.g. using
41 // library like libFuzzer.
42 class Mutator {
43  public:
44   // seed: value to initialize random number generator.
45   explicit Mutator(RandomEngine* random);
46   virtual ~Mutator() = default;
47 
48   // message: message to mutate.
49   // size_increase_hint: approximate number of bytes which can be added to the
50   // message. Method does not guarantee that real result size increase will be
51   // less than the value. It only changes probabilities of mutations which can
52   // cause size increase. Caller could repeat mutation if result was larger than
53   // requested.
54   void Mutate(protobuf::Message* message, size_t size_increase_hint);
55 
56   void CrossOver(const protobuf::Message& message1,
57                  protobuf::Message* message2);
58 
59  protected:
60   // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
61   virtual int32_t MutateInt32(int32_t value);
62   virtual int64_t MutateInt64(int64_t value);
63   virtual uint32_t MutateUInt32(uint32_t value);
64   virtual uint64_t MutateUInt64(uint64_t value);
65   virtual float MutateFloat(float value);
66   virtual double MutateDouble(double value);
67   virtual bool MutateBool(bool value);
68   virtual size_t MutateEnum(size_t index, size_t item_count);
69   virtual std::string MutateString(const std::string& value,
70                                    size_t size_increase_hint);
71 
72   // TODO(vitalybuka): Allow user to control proto level mutations:
73   //   * Callbacks to recursive traversal.
74   //   * Callbacks for particular proto level mutations.
75 
random()76   RandomEngine* random() { return random_; }
77 
78  private:
79   friend class FieldMutator;
80   friend class TestMutator;
81   void InitializeAndTrim(protobuf::Message* message, int max_depth);
82   void CrossOverImpl(const protobuf::Message& message1,
83                      protobuf::Message* message2);
84   std::string MutateUtf8String(const std::string& value,
85                                size_t size_increase_hint);
86 
87   bool keep_initialized_ = true;
88   RandomEngine* random_;
89 };
90 
91 }  // namespace protobuf_mutator
92 
93 #endif  // SRC_MUTATOR_H_
94